什么是Vuex?
引用官方加以我自己的理解:
Vuex 是一个专门为 Vue.js 应用程序开发的状态管理器. 它采用集中式存储应用程序中组件可能会用到的组件数据(也可以叫状态).并以相应的规则(mutations用commit,actions用dispatch)保证状态可以以一种可以预测的方式发生变化.结合官方出品的DevTools Extension,可以方便的进行vuex状态跟踪和数据调试.
解释理解
读了官方这么一段文字.
大概了解了,Vuex 类似于提供了一个全局的单例大对象.
所有的状态数据操作都可以通过这个单例的大对象来进行.
这样就能保证数据的统一集中管理.
这里明明存放的数据,为什么要叫状态呢?(咬文嚼字一下?)
因为 vuex
不仅仅只是提供了一个大对象这么简单.
具体来说,它提供了一个具备响应式的大对象.
在vuex中定义的属性都是响应式的(reactive),这些响应式的数据又被组件依赖.
所以,这里叫状态可能比数据更为合适.
我们用代码访问到vuex的数据属性,本质上全被Object.defineProperty()给处理过了(所谓的数据劫持).
所以,我们访问的不是字段,而是属性访问器.
Vuex 基本使用
step 1 下载vuex插件
npm i --save vuex
step 2 注册vuex插件
import Vuex from 'vuex'
Vue.use(Vuex)
step 3 添加vuex模块
// store.js
const store = {
state : {
firstName: '',
lastName: ''
},
getters: {
getData (state) {
return state.firstName + '--' + state.lastName
}
},
mutations: {
changeData (state,payload) {
state.firstName = payload.firstName
state.lastName = payload.lastName
}
},
actions: {
changeDataAsync({dispatch,commit},payload) {
setTimeout(() => {
commit('changeData',{firstName:'Lee',lastName:'Bruchs'})
}, 3000)
}
}
}
step 4 在根组件内部注册vuex属性
import store from './store.js'
new App ({
...
store,
})
Vuex 模块的四大属性
- state 用于存储实际数据(实际上,被Object.defineProperty劫持了)
- getters 类似组件的 computed ,有缓存机制.
- mutations 同步修改数据用此方法.(搭配devtool可以追踪每一步的变化)
-
actions 用于异步修改数据,正确的操作姿势是:
在actions用异步获取数据,然后在其内部同步的调用commit来修改数据.
补充说明:
state
- 实际存放数据的位置(可以说是字段)
- 被 Object.defineProperty 劫持(提供reactive功能)
getters
- 类似于computed.
- 用于筛选和过滤state中的数据.
- 有缓存机制.
mutations
- 同步修改数据.
- 接受两个参数 (state,payload)
- 在模块内部直接 state.xxx = payload.xxx
- 在使用vuex的组件内强烈建议使用
this.$store.commit('mutaitonName',payload)
.因为为了这样Vuex提供的状态追踪才有会效果,搭配devtool才能正常的工作. 而不建议使用this.$store.state.data=xxx.这样vuex将无法追踪数据变化,也就无法愉快的使用devtool.
actions
- 异步操作放在
actions
中. - 实际上
actions
或默认返回promise
- 接受两个参数(ctx,payload)
- 其中 ctx 可以理解成当前的 store 对象. 里面有 commit (用于提交mutations) 和 dispatch(用于分发其他的action)
- 正确的使用方式是: 在 actions 中异步更新完毕数据之后,使用 commit 来同步数据更新.
- 在组件中只能使用 this.$store.dispatch('actionName',payload)(这里不涉及辅助函数)
Vuex 使用模块.
当数据越来越庞大的时候,仅仅一个大对象单例来存储的话,可能就不好管理和维护了.
可以利用 vuex 提供的 modules
来设置新的模块.
新的模块和普通模块(或者这里说rootModule)声明没有任何区别.
也是 state|getters|mutations|actions四个必要属性(当然也可以使用modules,来实现模块嵌套).
在声明模块时,最总要的一个属性是 namespaced:boolean
namespaced:false
- state 声明不冲突.(调用则是 this.$store.state.module.xxx)在调用级别就已经区分模块了)
- getters 无法声明成同名的.(否则会报命名重复冲突)
- mutations 和 actions 将会编译成全局的.将同名的mutations和actions丢在一个数组里.调用其中任何一个都会触发全部同名的mutations和actions调用.
所有的冲突都来自:我们在学vuex,懒的给不同模块的actions,mutations,state,getters起不同的名字,于是名字就起的是一样的.于是就造成了所谓的冲突.
namespaced:true
- state 不冲突.
- getters 也不冲突.
- mutations 也不冲突.
- actions 仍然不冲突.
但是上述对应的调用需要执行路径
比如在 second 模块下注册的这些属性.
- 'second/getter' --> 才能调用第二个模块指定的getter
- 'second/mutation' --> 才能调用第二个模块指定的mutation
- 'second/action' --> 才能调用第二个模块指定的action
vuex内容很稀碎.具体的都写在代码中了,直接看可能更直观.
具体代码例子在码云: