目录
3.等等,如果是这样的话,为什么官方还要专门出一个插件Vuex呢?难道我们不能自己封装个对象来管理吗?
3.Mutation(vuex的 store状态的更新唯一方式:提交 Mutation)
一、概念
1.什么是vuex?
官方解释:Vuex是一个专为Vue.js应用程序开发的状态管理模式。
它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex也集成到Vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试、状态快照导入导出等高级调试功能。
2.状态管理到底是什么?
状态管理模式、集中式存储管理这些名词听起来就非常高大上,让人捉摸不透。
其实,你可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面。
然后,将这个对象放在顶层的Vue实例中,让其他组件可以使用。
那么,多个组件是不是就可以共享这个对象中的所有变量属性了呢?
3.等等,如果是这样的话,为什么官方还要专门出一个插件Vuex呢?难道我们不能自己封装个对象来管理吗?
当然可以,只是我们要先想想 Vuejs帯给我们最大的便利是什么呢?没错,就是响应式。
如果你自己封装实现一个对象能不能保证它里面所有的属性做到响应式呢?当然也可以,只是自己封装可能稍微麻频一些。
不用杯疑,Vuex就是为了提供这样一个在多个组件间共享状态的插件,用它就可以了。
4.管理什么状态呢?
但是,有什么状态时需要我们在多个组件间共享的呢?
如果你做过大型开发,你一定遇到过多个状态,在多个界面间的共享问题。
比如用户的登录状态、用户名称、头像、地理位置信息等等。
比如商品的收藏、购物车中的物品等等。
这些状态信息,我们都可以放在统一的地方,对它进行保存和管理,而且它们还是响应式的(待会儿我们就可以看到代码了,莫着急)。
二、.单界面的状态管理
这图片中的三种东西,怎么理解呢?
State:不用多说,就是我们的状态。(你姑且可以当做就是data中的属性)
View:视图层,可以针对State的变化,显示不同的信息。
Actions:这里的Actions主要是用户的各种操作:点击、输入等等,会导致状态的改变。
例如,下面的例子一定会实现吧:
三、多界面的状态管理-vuex。
1.安装vuex
npm install vuex --save
2.vuex是如何实现多界面状态管理的
vue已经帮我们做好了单个界面的状态管理,但是如果是多个界面呢?
口多个组件都依赖同一个状态(一个状态改了,多个界面需要进行更新)
口不同界面的 Actions都想修改同一个状态( Home.vue需要修改, Profile.vue也需要修改这个状态)
也就是说对于某些状态(状态1/状态2/状态3)来说只属于我们某一个组件,但是也有一些状态(状态a/状态b/状态c)属于多个组件共同想要维护的
口状态1/状态2/状态3你放在自己的房间中,你自己管理自己用,没问题
口但是状态a/状态b/状态c我们希望交给一个大管家来统·帮助我们管理!!!
口没错,vuex就是为我们提供这个大管家的工具
全局单例模式(大管家)
口我们现在要做的就是将共享的状态抽取出来,交给我们的大管家,统一进行管理。
口之后,你们毎个组件,按照我规症好的规定,进行访问和修改等操作。
口这就是vuex背后的基本思想
3.官方给出的一幅图
devtools:浏览器插件,可以帮助记录修改之后state的状态。
修改state只有通过Mutations修改才能进行跟踪!直接修改state虽然也能改但是无法跟踪($store.state.count++)
Actions:做异步操作使用Actions;Mutations只能处理同步操作。
4.安装谷歌devtools插件
5.使用Mutations
export default new Vuex.Store({
state: {
count: 100
},
mutations: {
// 方法,只有使用这个修改数值,才能监控到state的变化
increment(state) {
state.count ++
},
decrement(state) {
state.count --
}
}
})
调用mutations中的方法修改state:
this.$store.commit('increment')
获取state数据:
$store.state.count
五、vuex的核心概念
1.State,单一状态树
定义:
state: {
count: 100
}
使用:
$store.state.count
vuex提出使用单一状态树什么是单一状态树呢?
口英文名称是 Single Source of Truth,也可以翻译成单一数据源
但是,它是什么呢?我们来看个生活中的例子。
口OK,我用个生活中的例子做一个简单的类比。
口我们知道,在国内我们有很多的信息需要被记录,比如上学时的个人档案,工作后的社保记录,公积金记录,结婚后的婚姻信息,以及其他相关的户口、医疗、文凭、房产记录等等(还有很多信息)。
口这些信息被分散在很多地方进行管理,有天你需要办某个业务时(比如入户某个城市),你会发现你需要到各个对应的工作地点去打印、盖章各种资料信息,最后到个地方提交证明你的信息无误。
口这种保存信息的方案,不仅仅低效,而且不方便管理,以及日后的维护也是一个庞大的工作(需要大量的各个部门的人力来维护,当然国家目前已经在完普我们的这个系统了)。
这个和我们在应用开发中比较类似
口如果你的状态信息是保存到多个 Store对象中的,那么之后的管理和维护等等都会变得特别困难。
口所以Vuex也使用了单一状态树来管理应用层级的全部状态。
口单状态树够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。
2.Getters(类似于计算属性computed)
(1)getters基本使用
(2)getters中使用getters:
(3)获取getters中的方法
{{$store.getters.countDouble}}
(4)getters传参
getters: {
countDouble(state) {
return state.count * 2
},
mutaByMe(state){
// 返回一个函数,可以使用箭头函数,并且只有一行的话默认就是返回值,并不推荐写的太简洁,因为可读性很差
// return function(ct) {
// return state.count * ct
// }
return ct => state.count * ct
}
}
使用:
<h2>{{$store.state.count * 2}}</h2>
<h2>{{$store.getters.countDouble}}</h2>
<h2>{{$store.getters.mutaByMe(5)}}</h2>
3.Mutation(vuex的 store状态的更新唯一方式:提交 Mutation)
(1)Mutation主要包括两部分:
口字符串的事件类型(type)
口一个回调函数( handler),该回调函数的第一个参数就是 state。
(2)Mutation基本使用
(3)Mutation传参(多个参数的话,可以封装到一个对象中)
mutations: {
// 方法,只有使用这个才能监控到state的变化
add5(state, ct){// payload负载
state.count = state.count + ct
}
}
this.$store.commit('add5', ct)
(4)Mutation提交风格
上面通过commit进行的提交是一种普通的方式。
Vue还提供了另外一种风格,它是一个包含type属性的对象
Mutation中的处理方式是将整个commit的对象作为payload使用,所以代码没有改变,依然如下:
此时获取的payload就是commit里面的完整对象。
(5)Mutation响应规则
Vuex的 store中的 state是响应式的,当 state中的数据发生改变时,Vue组件会自动更新。
定义在state中的属性都被会加入到响应式系统中,而响应式系统会监听属性的变化,当属性发生变化时,会通知所有界面中用到该属性的地方,让界面发生刷新。
这就要求我们必须遵守一些Vuex对应的规则:
口提前在 store中初始化好所需的属性(store中对象已经定义好的属性是可以实现响应式的)
口当给 state中的对象添加新属性时,使用下面的方式方式
方式一:使用 Vue.set(obj, 'newProp',123)
方式二:用新对象给旧对象重新赋值
例如:
1.在state中定义info: {'name':'zs', 'age': 15}。
2.直接在Mutation中修改属性值是可以实现响应式的
state.info.name = 'ls'
3.这样新增属性值是做不到响应式的:
state.info['address'] = '山东'
4.新增属性需要这样做,才能实现新属性的响应式:
Vue.set(state.info, 'address', '山东')
5.删除属性这样做也不是响应式:
delete state.info.age
6.删除属性这样做才是响应式:
Vue.delete(state.info, 'age')
7.直接将state中完整的对象重新赋值也可以实现响应式
state.info = {xxxx}
(6)Mutation类型常量
我们来考虑下面的问题:
口在 mutation中,我们定义了很多事件类型(也就是其中的方法名称)
口当我们的项目增大时,Vuex管理的状态越来越多,需要更新状态的情况越来越多,那么意味着 Mutation中的方法越来越多
口方法过多,使用者需要花费大量的精力去记住这些方法,甚至是多个文件间来回切换查看方法名称,甚至如果不是复制的时候可能还会出现写错的情况
(7)Mutation同步代码
通常情况下,Vuex要求我们 Mutation中的方法必须是同步方法
口主要的原因是当我们使用 devtools时,可以 devtools可以帮助我们捕捉 mutation的快照
口但是如果是异步操作,那么 devtools将不能很好的追踪这个操作什么时候会被完成
所以,不要在Mutation中进行任何异步操作。
4.Actions
(1)定义actions(其中需要调用mutations方法进行参数的修改,具体参照官网的图)
actions: {
// context 上下文
aUpdateInfo(context){
setTimeout(() => {
context.commit(INCREAMENT)
}, 1000)
}
}
(2)使用action
this.$store.dispatch('aUpdateInfo')
(3)传参参考mutations
(4)异步回调
5.Module
(1)Module是模块的意思,为什么在Vuex中我们要使用模块呢
口Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理
口当应用变得非常复杂时,store对象就有可能变得相当臃肿
口为了解决这个问题Vuex允许我们将 store分割成模块( Module),而每个模块拥有自己的 state、 mutation、action、 getters等
(2)上面的代码中,我们已经有了整体的组织结构,下面我们来看看具体的局部模块中的代码如何书写。
我们在moduleA中添加state、mutations、getters
mutation和getters接收的第一个参数是局部状态对象
六、项目结构