Description
前言
在vue里,组件之间的作用域是独立的,父组件跟子组件之间的通讯可以通过prop属性来传参,但是在兄弟组件之间通讯就比较麻烦了。比如A组件要告诉一件事给B组件,那么A就要先告诉他们的爸组件,然后爸组件再告诉B。当组件比较多,要互相通讯的事情很多的话,爸组件要管他们那么多事,很累的。vuex正是为了解决这个问题,让多个子组件之间可以方便的通讯。
项目介绍
待办事项中的一个事件,它可能拥有几个状态,未完成、已完成、已取消或被删除等。这个事件需要在这多种状态之间切换,那么使用vuex来管理也是非常方便的。
来看一下vuex怎么完成状态管理的:
所有组件都是调用actions,分发mutation去修改state,然后state经过getter又更新到各个组件里。state又通过localStorage存储数据到本地,下次重新打开时再读取保存的数据。
模块化
为什么要用模块化?当我们的项目比较大,组件很多,功能也多,会导致state里要存放很多内容,整个 store 都会很庞大,很难管理。
我模块化的store目录如下:
|-store/ // 存放vuex代码
| |-eventModule // 事件模块
| | |-actions.js
| | |-getters.js
| | |-index.js
| | |-mutations.js
| | |-state.js
| |-themeModule // 主题颜色模块
| | |-actions.js
| | |-getters.js
| | |-index.js
| | |-mutations.js
| | |-state.js
| |-index.js // vuex的核心,创建一个store
可以看到,每个模块拥有自己的state、mutation、action、getter,这样子我们就可以把我们的项目根据功能划分为多个模块去使用vuex了,而且后期维护也不会一脸懵逼。
状态管理
接下来,我们来看看vuex完成状态管理的一个流程。
举个栗子:一个待办事项,勾选之后,会在未完成列表里移除,并在已完成的列表里出现。这个过程,是这个待办事项的状态发生了改变。勾选的时候,是执行了一个方法,那我们就先写这个方法。在 event_list.vue 文件里新建一个moveToDone方法。
methods: {
moveToDone(id){ //移至已完成
this.$store.dispatch('eventdone', id);
}
}
在 moveToDone 方法中通过 store.dispatch 方法触发 action, 接下来我们在 eventModule/actions.js 中来注册这个 action, 接受一个 id 的参数。
export default {
eventdone = ({ commit }, param) =>{
commit('EVENTDONE',{id: param});
}
}
action 通过调用 store.commit 提交载荷(也就是{id: param}这个对象)到名为'EVENTDONE'的 mutation,那我们再来注册这个 mutation
export default {
EVENTDONE(states,obj){
for (let i = 0; i < states.event.length; i++) {
if (states.event[i].id === obj.id) {
states.event[i].type = 2;
states.event[i].time = getDate();
var item = states.event[i];
states.event.splice(i, 1); // 把该事件在数组中删除
break;
}
}
states.event.unshift(item); // 把该事件存到数组的第一个元素
local.set(states); // 将整个状态存到本地
}
}
通过 mutation 去修改 state, state里我们存放了一个 event 属性
export default {
event: []
};
在组件中要获得这个 state 里的 event, 那就需要写个getters
export default {
getDone(states){
return states.event.filter(function (d) {
if (d.type === 2) { // type == 2表示已完成
return d; // 返回已完成的事件
}
});
}
};
然后每个module里都有一个index.js文件,把自己的state、mutation、action、getters都集合起来,就是一个module
import * as func from '../function';
import actions from './actions.js';
import mutations from './mutations.js';
import state from './state.js';
import getters from './getters.js';
export default {
state,
getters,
actions,
mutations
}
在 store/index.js 里创建一个 store 对象来存放这个module
import Vue from 'vue';
import Vuex from 'vuex';
import event from './eventModule';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
event
}
});
最后在 event_list.vue 组件上,我们通过计算属性 computed 来获取到这个从未完成的状态改变到已完成的状态,我们要用到 store 这个对象里的getters
computed: {
getDone(){
return this.$store.getters.getDone;
}
}
这样子,完成了 '未完成' => '已完成' 从提交修改到更新视图读取的整个流程,也是 vuex 工作的整个流程。通过 module 的封装,更加方便多模块项目的开发和维护。
Activity
libin1991 commentedon Mar 15, 2017
有报错啊
lin-xin commentedon Mar 15, 2017
@libin1991 报什么错啊
totchina commentedon Mar 15, 2017
非常详细,谢谢
ghost commentedon Mar 16, 2017
localEvent.js?961b:20 Uncaught ReferenceError: lx_notepad is not defined
at eval (eval at (app.js:723), :19:28)
at Object. (app.js:723)
at webpack_require (app.js:660)
at fn (app.js:84)
at Object.eval (eval at (app.js:877), :1:119)
at eval (eval at (app.js:877), :22:30)
at Object. (app.js:877)
at webpack_require (app.js:660)
at fn (app.js:84)
at Object.eval (eval at (app.js:898), :3:65)
ghost commentedon Mar 16, 2017
报的这个错 lx_notepad这个东西是什么?
lin-xin commentedon Mar 16, 2017
@liangxuxuxu 这个是本地存储的 item 名
ghost commentedon Mar 16, 2017
现在我该怎么改这个 直接存在locastorage里面吗?
orallin commentedon Mar 16, 2017
报错……node_modules下不来~你用的应该是mac吧
lin-xin commentedon Mar 16, 2017
@orallin 我用windows啊,你用 cnpm 试试。
AquariusBaby commentedon Mar 22, 2017
楼主大大,你项目里我咋没看到webpack.config啊,新手勿喷,谢谢!
lin-xin commentedon Mar 23, 2017
@AquariusBaby 项目用vue-cli生成的,在build/webpack.base.conf.js就是了。
AquariusBaby commentedon Mar 23, 2017
恩恩,看到了,之前一直用的webpack-simple。^-^
leochen-g commentedon Jul 12, 2017
非常不错的解释,正在找Vuex的详解呢
Dzhaolei commentedon Aug 1, 2017
一脸懵逼的来,一脸懵逼的走
QTTQ commentedon Sep 4, 2017
吊炸天,但还有点蒙蒙的
Harrymiracle commentedon Sep 16, 2017
非常受用 谢谢!
InterfaceYang commentedon Sep 20, 2017
楼主大大,vue.use(vuex) 会提示vuex只能install一次,,,,,然后就没有然后了
Luying0829 commentedon Aug 23, 2018
我的也报错...... node_modules下载了,但是npm run dev 就是跑不起来
用了CNPM试了下,也不行 一直报错
mmfishlxy commentedon Aug 13, 2019
做得特别棒 正在看你的代码