官方文档
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化
准备工作
js引入方式
<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>
npm引入方式
npm install vuex --save
模块化的打包系统中
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
1、创建index.js文件
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
导入对应的组件状态管理文件
import State from './state';
统一在vuex的store对象中管理
const store = new Vuex.Store(State);
导出
export default store;
2、创建state.js文件
export default {
state: {
test: 0,
},
mutations:{
'test': function(state, value) {
state.test = value;
}
},
getters:{
'test': function(state) {
return state.test;
}
}
};
--提交值
this.$store.commit('key',更新的内容);
--获取值 用变量进行接受
this.$store.getters.key
3、引入项目中
在vue入口中引入store文件
import store from './store';
根组件注入store 的机制
new Vue({
el: '#app',
store: store,
});
单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性 (opens new window)中返回某个状态:
// 创建一个 Counter 组件
const Counter = {
template: `{
{ count }}`,
computed: {
count () {
return store.state.count
}
}
}
在store.js中:
state: {
test: 0,
},
每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
Vue.use(Vuex):通过调用此vuex 外,在根组件中引入store,可以注入到每一个子组件中。子组件就能实时得到相应的数据
mapState:组件需要获取多个状态,生成计算属性,函数返回的是一个对象。
computed:监控自己定义的百年来那个,改变量不在data中定义,直接在computed中定义,最好的场景就是页面动态显示的结果,可以放到此处进行计算监控和显示
computed: {
localComputed () {
/* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
}
就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算
getters: {
test:function(state){
return state.test;
}
}
this.$store.getters.test;
这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
提交载荷(Payload)
可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload)
使用常量替代 Mutation 事件类型
使用文件单独放置常量,来进行系统引用
export const SOME_MUTATION = ‘SOME_MUTATION’
Mutation 必须是同步函数
mutations:{
'test': function(state, value) {
state.test = value;
}
}
this.$store.commit('test',内容);
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation
actions: {
increment ({
commit }) {
commit('test')
}
}
分发 Action
Action 通过 store.dispatch 方法触发
store.dispatch('increment')
Actions 支持同样的载荷方式和对象方式进行分发:
// 以载荷形式分发
store.dispatch('test', {
amount: 10
})
// 以对象形式分发
store.dispatch({
type: 'test',
amount: 10
})
在组件中分发 Action
import {
mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
组合 Action
actions: {
async actionA ({
commit }) {
commit('gotData', await getData())
},
async actionB ({
dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 完成
commit('gotOtherData', await getOtherData())
}
}
为了解决store 对象变得相当臃肿问题,vuex允许我们将store分割成模块,每个模块都有自己的state、mutation、action、getter、子嵌套模块
const moduleA = {
state: () => ({
... }),
mutations: {
... },
actions: {
... },
getters: {
... }
}
const moduleB = {
state: () => ({
... }),
mutations: {
... },
actions: {
... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
加入namespaced: true 开启命名空间
const store = new Vuex.Store({
modules: {
account: {
namespaced: true,
// 模块内容(module assets)
state: () => ({
... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
getters: {
isAdmin () {
... } // -> getters['account/isAdmin']
},
actions: {
login () {
... } // -> dispatch('account/login')
},
mutations: {
login () {
... } // -> commit('account/login')
},
// 嵌套模块
modules: {
// 继承父模块的命名空间
myPage: {
state: () => ({
... }),
getters: {
profile () {
... } // -> getters['account/profile']
}
},
// 进一步嵌套命名空间
posts: {
namespaced: true,
state: () => ({
... }),
getters: {
popular () {
... } // -> getters['account/posts/popular']
}
}
}
}
}
})
以下分为两种使用情况
在带命名空间的模块内访问全局内容(Global Assets)
此处不是太理解…后面视频学习
在带命名空间的模块注册全局 action
root: true, 开启当前模块action全局模式
{
actions: {
someOtherAction ({
dispatch}) {
dispatch('someAction')
}
},
modules: {
foo: {
namespaced: true,
actions: {
someAction: {
root: true,
handler (namespacedContext, payload) {
... } // -> 'someAction'
}
}
}
}
}
仅供开发环境使用
import createLogger from 'vuex/dist/logger'
日志:plugins: [createLogger()]
严格模式:strict: true
const store = new Vuex.Store(
{
plugins: [createLogger()],State,strict: true});
需要插件和专属配置支持、比较麻烦
需要支持 mutation 和模块,你需要使用 store.hotUpdate() 方法:
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations'
import moduleA from './modules/a'
Vue.use(Vuex)
const state = {
... }
const store = new Vuex.Store({
state,
mutations,
modules: {
a: moduleA
}
})
if (module.hot) {
// 使 action 和 mutation 成为可热重载模块
module.hot.accept(['./mutations', './modules/a'], () => {
// 获取更新后的模块
// 因为 babel 6 的模块编译格式问题,这里需要加上 `.default`
const newMutations = require('./mutations').default
const newModuleA = require('./modules/a').default
// 加载新模块
store.hotUpdate({
mutations: newMutations,
modules: {
a: newModuleA
}
})
})
}
在此声明,以上内容部分列子来于官方文档