VUE学习笔记--vuex
1、vuex是干啥的
官网的说法是 vuex是一个专为vue应用程序开发的状态管理模式。
通俗的说,是用来管理组件间共享变量的。
1、我们能自己封装一个对象来管理共享变量吗?
当然可以,只是除了要管理共享变量,我们也不能抛弃vue最大的特点“响应式”,如果再加上响应式,其实这就是vuex了。我们当然可以自己实现这些功能,但一般来说官方的轮子总是比我们自己造的要好一些的。
2、有哪些状态需要在组件间共享呢?
没有严格的定义;一般来说,比如用户的登录状态、名称、头像、地理位置信息,或者购物车、收藏等内容是系统内很多地方需要访问的内容,这些内容就可以放到vuex中,既方便了处理,也仍然有响应式。一些临时性质的,仅仅在一两个组件共享的对象,一般不建议放到vuex中,以避免vuex过于复杂。
2、vuex的使用
跟普通插件一样:
//1、安装插件
Vue.use(Vuex)
//2、创建对象
const store = new Vuex.Store({
state:{ //单一状态树
},
mutations:{},//用于提交的方法
actions:{}, //异步操作
getters:{}, //类似于计算属性
modules:{} //模块划分
})
//3、导出store对象
export default store
//4、使用
new Vue({
el: '#app',
store,
render: h => h(App)
})
//5、完成4以后会在原型上绑定数据 Vue.prototype.$store = store ;我们可以在需要的地方$store来引用;
为了处理并发修改的问题,vuex设计了一套状态机制,用来跟踪数据状态变更;虽然可以直接修改数据,但仍强烈建议通过状态机制修改。
3、状态管理的使用
vuex的状态关系图:
异步操作一般在actions进行,需要操作状态对象,则通过commit方法调用Mutations中的方法。这样操作,会将状态变更纳入vuex的状态跟踪机制,利用vue提供的插件Devtools可以清楚的看到数据状态的变化。
以点击按钮,对某数值进行递增为例,正确用法为:
//在vuex中,声明变量跟方法
const store = new Vuex.Store({
state:{
counter: 1000,
students:[
{name:'zhangsan',age:10},
{name:'lisi',age:15},
{name:'wangwu',age:20},
{name:'maliu',age:25},
{name:'zhengqi',age:30}
]
},
mutations:{
//方法
increment(state){
state.counter ++
},
addStudent(state, stu){
state.students.push(stu);
}
},
actions:{},
getters:{
//年龄大于20的学生列表
more20stu(state){
return state.students.filter(s => s.age > 20)
},
//年龄大于20的人数,第二个参数为getter
more20studentLength(state, getter){
return getter.more20stu.length
},
//可以返回函数
moreAgeStu(state){
return function(age){
return state.students.filter(s => s.age > age)
}
}
},
modules:{}
})
//在vue中用方法进行响应
export default {
methods:{
addition(){
//注意这里是commit去调用的
this.$store.commit('increment')
}
}
}
单一状态树:Single Source of Truth,直译应为单一数据源。 vuex是可以建多个store对象的,但这不方便管理维护,vuex建议只用一个store实例,这个实例就是所谓的单一状态树。
mutations: 定义方法,用于响应外部提交的方法;只有通过这种方式对state数据进行的访问,才会被纳入状态管理,vue官方强烈建议采用该种方式。通过mutation更新数据时,也可以额外携带一些参数,这些参数被称为载荷(payload);
getters: 跟cumputed类似,可以获取变化的属性;方法有两个参数,第一个为state本身,第二个为getter;除了可以返回计算结果,也可以返回函数。
4、响应规则
Vuex的store中的state是响应式的,当state中的数据发生变化时,vue组件会自动更新。但这要求我们必须遵守一些vuex对应的规则:
1、提前在store中初始化好所需的属性
2、当给state中的对象添加新属性时,使用如下方式:
a、使用Vue.set(obj, '属性名', '属性值')
b、用新对象给旧对象重新赋值
另外,通常情况下,Vuex要求我们Mutation中的方法必须是同步方法,主要原因是当我们使用devtools时,devtools可以帮我们捕捉mutation的快照,但如果是异步操作,那么devtools将不能很好的追踪这个操作什么时候完成。但如果的确需要在vuex中进行一些异步操作,该如何实现呢,使用action!action跟mutation类似,只是用来处理异步操作。
需要注意的是,在action进行了异步操作之后,不能跳过mutation直接修改数据状态,仍要调用mutation中的方法,来实现数据状态的监控。这里可以跟promise结合,使代码更优雅。
提交mutation用commit,提交action用dispatch。
5、modules模块划分
modules 模块划分,避免状态过多问题;
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const moduleA = {
state:{
a:{name:"张三",age:20}
},
mutations:{
updateName(state){
state.a.name = '李四'
}
}
}
const store = new Vuex.Store({
state:{
counter: 1000,
students:[
{name:'zhangsan',age:10},
{name:'lisi',age:15},
{name:'wangwu',age:20},
{name:'maliu',age:25},
{name:'zhengqi',age:30}
]
},
mutations:{
increatment(state){
state.counter ++;
},
decrement(state){
state.counter --;
}
},
actions:{},
getters:{
powerCounter(state){
return state.counter * state.counter
}
},
modules:{
obj: moduleA
}
})
export default store
使用可以如下:
<span>moduleA:{{$store.state.obj.a.name}}</span>
6、代码结构
将vuex的各个部分,比如action,mutation等抽取为独立的文件,modules也单独文件夹处理,参考目录如下:
|-- index.html
|-- main.js
|-- api
| |-- # 抽取出api请求
|
|-- components
| |-- App.vue
| |
| |-- ...
|
|-- store
|-- index.js #组装并导出store的地方
|-- actions.js #根级别的action
|-- mutations.js #根级别的mutation
|-- modules
|-- cart.js #购物车模块
|-- product.js #产品模块