前言
本文将从Vuex的核心概念出发,通过讲解一个待办清单的小项目,帮助大家更好的理解Vuex。此文主要是根据近日学习的关于Vuex的内容,整理出的学习笔记,用来巩固与记录。欢迎大家交流与讨论!😊
主要参考视频为黑马程序员的“Vue全家桶-Vuex” 原视频地址 https://www.bilibili.com/video/BV1h7411N7bg?from=search&seid=5930582975536399924&spm_id_from=333.337.0.0 若有侵权,请邮箱联系1544945335@qq.com 联系,我会及时删除。敬礼!
一、Vuex是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 参考教程:https://vuex.vuejs.org/zh/
那么什么是状态管理模式呢?在一般情况下,我们的vue应用在渲染数据时,是一个单项数据流的过程,驱动的数据源为状态,状态会以声明方式映射到视图,用户通过在视图上操作又会导致状态变化。如图所示:
我们多个视图依赖同一状态(数据)、或不同的视图需要变更同一状态(数据)时,若没有一个统一的状态管理器,但是又需要实现数据共享时,过程就会变得麻烦。按照传统方式,我们是可以通过各个组件传参来达成数据共享,但若项目变大,传参的过程就会变得相当繁琐,且后期维护的成本也很高。 所以Vuex作为一个状态管理器,可以把不同组件的共享状态抽离出来,集中管理便于后期维护,并利用vuex的响应式的特点从而实现高效进行状态更新。
Vuex核心概念
在安装好vuex之后,将出现store文件夹,里面有index.js的文件,代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
下面将一一介绍Store的核心。
1. State
State为Vuex的公共状态,提供唯一的数据源,用来存储公共的数据。
- 例如我们将要实现todoList的列表事项就可以作为公共数据放在state中。
代码如下:
state: {
list: [],
},
当我们要访问存放在State里面的数据可通过以下两种方式:
- 组件访问State中数据的第一种方式:
this.$stroe.state.全局数据名称
- 组件访问State中数据的第二种方式:
import { mapState } from 'vuex'
computed: {
...mapState(['list']),
},
2. Mutations
Mutations用于变更Store中的数据。
- 只能通过mutations变更Store数据,不可以直接操作Store中的数据。
假设要实现一个点击自增的功能,首先需要在Store中定义Mutations代码如下:
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
add(state){
state.count++
}
addN(state,n){
state.count += n
}
},
})
触发mutations需通过以下两种方式:
- 触发mutations的第一种方式:
methods: {
handle() {
this.$store.commit('add')
}
}
methods: {
handle1() {
this.$store.commit('addN',n)
}
}
- 触发mutations的第二种方式:
import { mapMutations } from 'vuex'
methods: {
...mapMutations(['add']),
handle(){
this.add()
},
handle1(){
this.addN(5)
}
},
3.Actions
Actions用于处理异步任务
- 如果通过异步操作变更数据,必须通过Actions,而不能使用Mutations
- 在Actions中还是要通过触发Mutations方式变更数据
假设要实现一个延时添加的功能,在Store中定义actions代码如下:
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
add(state){
state.count++
}
},
actions: {
addAsync(context) {
setTimeout(() => {
context.commit('add')
}, 1000)
}
},
})
触发actions可通过以下两种方式:
- 触发actions的第一种方式:
methods: {
handle() {
this.$store.dispatch('addAsync')
}
}
- 触发actions的第二种方式:
import { mapAction } from 'vuex'
methods: {
...mapActions(['addAsync']),
},
4.Getters
Getters用于对Store中的数据进行加工处理形成新的数据。
- Getter可以对Store中的数据进行加工处理形成新的数据,类似Vue的计算属性
- Store中数据发生变化,Getters的数据也会发生变化
在Store中定义Getter代码如下:
export default new Vuex.Store({
state: {
count: 0
},
getters: {
showNum(state) {
return '当前最新的数量是【' + state.count + '】'
},
}
},
})
使用getters可通过以下两种方式:
- 使用getters的第一种方式:
this.$store.getters.名称
- 使用getters的第二种方式:
import { mapGetters } from 'vuex'
computed: {
...mapGetters(['showNum']),
},
(携带参数)
二、todoList待办清单
源码:https://gitee.com/wx_f6a2d8acc5/vuex-to-do-list.git
1.初始化项目-基于已有样式模版实现Todos基本布局
我们的待办清单基本布局与功能点如上图所示
html代码如下:
<template>
<div id="app">
<a-input
placeholder="请输入任务"
class="my_ipt"
:value="inputValue"
@change="handleInputChange"
/>
<a-button type="primary" @click="addItemToList">添加事项</a-button>
<a-list bordered :dataSource="list" class="dt_list">
<a-list-item slot="renderItem" slot-scope="item">
<a-checkbox
:checked="item.done"
@change="cbStatusChanged($event, item.id)"
>{{ item.info }}</a-checkbox
>
<a slot="actions" @click="removeItemById(item.id)">删除</a>
</a-list-item>
<div class="footer" slot="footer">
<span>{{ unDoneLength }}条剩余</span>
<a-button-group>
<a-button
:type="viewKey === 'all' ? 'primary' : 'default'"
@click="changeList('all')"
>全部</a-button
>
<a-button
:type="viewKey === 'undone' ? 'primary' : 'default'"
@click="changeList('undone')"
>未完成</a-button
>
<a-button
:type="viewKey === 'done' ? 'primary' : 'default'"
@click="changeList('done')"
>已完成</a-button
>
</a-button-group>
<a @click="clean">清除已完成</a>
</div>
</a-list>
</div>
</template>
下面将按功能点分别介绍实现思路
2.使用axios获取数据
前端模拟数据可把list列表数据单独存放在一个json文件里,利用axios获取
字段释义:
id 待办清单项idinfo 待办清单项内容done 是否已完成(true 为已完成,false 为未完成)
list.json 代码如下:
[
{
"id": 0,
"info": "Racing car sprays burning fuel into crowd.",
"done": false
},
{
"id": 1,
"info": "Japanese princess to wed commoner.",
"done": false
},
{
"id": 2,
"info": "Australian walks 100km after outback crash.",
"done": true
},
{
"id": 3,
"info": "Man charged over missing wedding girl.",
"done": false
},
{
"id": 4,
"info": "Los Angeles bat∏tles huge wildfires.",
"done": false
}
]
在store/index.js 中,首先在state中定义数据
state: {
list: [],
},
在页面初始化时获取数据
created() {
this.$store.dispatch('getList')
},
Actions异步获取本地数据
actions: {
getList(context) {
axios.get('/list.json').then(({ data }) => {
console.log(data)
context.commit('initList', data)
})
},
addAsync(context) {
setTimeout(() => {
context.commit('add')
}, 1000)
}
},
Actions在mutation中对state数据进行赋值
mutations: {
initList(state, list) {
state.list = list
},
App.vue 中Actions在mutation中对state数据进行赋值
computed: {
...mapState(['list']),
},
3.添加列表事项
实现思路:
- 首先监听输入框内容,实时传给vuex
- vuex中mutations设置函数,实时获取到文本框输入的内容
- 点击添加,传给对应的mutations中的添加函数
- 在vuex的mutations的添加函数中,把列表项(一个对象)添加到state存储的数据中
App.vue 代码如下:
methods: {
handleInputChange(e) {
console.log(e.target.value)
this.$store.commit('setInputValue', e.target.value)
},
addItemToList() {
if (this.inputValue.trim().length <= 0) {
return this.$message.warning('输入内容不能为空')
} else {
this.$store.commit('addItem')
}
},
store/index.js 代码如下:
state: {
list: [],
inputValue: '',
nextId: 5,
},
mutations: {
setInputValue(state, val) {
state.inputValue = val
},
addItem(state) {
const obj = {
id: state.nextId,
info: state.inputValue.trim(),
done: false
}
state.list.push(obj)
state.nextId++
state.inputValue = ''
},
},
4.删除列表事项
实现思路:
- 首先获取到删除的id
- 点击删除,把对应的id传给对应的mutations中的删除函数
- 在vuex的mutations的删除函数中,筛选出对应id的对象,进行删除
App.vue 代码如下:
methods: {
removeItemById(id) {
this.$store.commit('removeItem', id)
},
},
store/index.js 代码如下:
mutations: {
removeItem(state, id) {
const i = state.list.findIndex((x) => x.id === id)
if (i !== -1) {
state.list.splice(i, 1)
}
},
},
5.选中标记已完成
实现思路:
- 利用组件的
change 属性,当列表选项选中状态改变时获取id以及当前选中状态 - 传给对应的mutations函数
- 在vuex的mutations的改变选中状态函数中,根据id找到列表项并更改选中状态
App.vue 代码如下:
cbStatusChanged(e, id) {
const param = {
id: id,
status: e.target.checked
}
this.$store.commit('changeStatus', param)
},
store/index.js 代码如下:
mutations: {
changeStatus(state, param) {
const i = state.list.findIndex((x) => x.id === param.id)
state.list[i].done = param.status
},
},
6.显示待完成条数
实现思路:
- 对已有list列表进行筛选
- 筛选出状态等于false的列表项
store/index.js 代码如下:
getters: {
unDoneLength(state) {
return state.list.filter((x) => x.done === false).length
},
},
7.切换tabs显示不同内容
实现思路:
- 切换tabs时首先tabs对应按钮的选中状态会改变,另外列表内容也会改变
- 给所有tabs(3个btn)绑定事件,当按钮点击时获取到当前选中的按钮内容,传给vuex
- vuex中state记录当前选中的按钮内容(全部、已完成、未完成)
viewKey - 根据
viewKey 的变化,同步更改所有按钮type值,并设置组件选中样式(当然也有更方便的组件,不需要我们自己写) - 根据
viewKey 的变化,更新列表的数据源,这里用Getters处理
App.vue 代码如下:
changeList(key) {
this.$store.commit('changeList', key)
}
store/index.js 代码如下:
mutations: {
changeList(state, key) {
state.viewKey = key
}
},
html代码如下:
<a-button-group>
<a-button
:type="viewKey === 'all' ? 'primary' : 'default'"
@click="changeList('all')"
>全部</a-button
>
<a-button
:type="viewKey === 'undone' ? 'primary' : 'default'"
@click="changeList('undone')"
>未完成</a-button
>
<a-button
:type="viewKey === 'done' ? 'primary' : 'default'"
@click="changeList('done')"
>已完成</a-button
>
</a-button-group>
store/index.js 代码如下:
getters: {
infoList(state) {
if (state.viewKey === 'all') {
return state.list
}
if (state.viewKey === 'undone') {
return state.list.filter((x) => x.done === false)
}
if (state.viewKey === 'done') {
return state.list.filter((x) => x.done === true)
}
return state.list
}
},
8.清除已完成
实现思路:
App.vue 代码如下:
methods: {
clean() {
this.$store.commit('clean')
},
},
store/index.js 代码如下:
mutations: {
clean(state) {
state.list = state.list.filter((x) => x.done === false)
},
},
总结
以上就是关于vuex的入门内容,本文仅仅简单介绍了vuex一些核心概念以及一个todoList待办清单的小例子!欢迎点赞评论收藏,一起学习一起进步!
|