Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
使用 Vue CLI 脚手架安装的 Vue 3.0 已经默认集成了 Vuex,下面记录的是 Vue 2.0 安装使用 Vuex 教程。
npm:
npm install vuex --save
yarn:
yarn add vuex
通过 Vue.use()
安装:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏。
我们可以把组件的共享状态抽取出来,以一个全局单例模式管理。
安装 Vuex 之后,在 /src
目录下 创建一个 store
文件夹,然后在该文件夹内创建一个 index.js
文件。
./src/store/index.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
然后在 /main.js 中引入并初始化 sotre :
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store: store,
}).$mount('#app')
这样就可以在任意页面调用 store 中的参数了:
console.log(this.$store.state.count)
# 0
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
State、Getter、Mutation、Action、Module
export default new Vuex.Store({
modules: {
},
state: {
},
getters: {
},
mutations: {
},
actions: {
}
})
State 单一状态树:
Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
this.$store.state.<name>
最佳实践:使用计算属性获得每次 state 中变化 :
computed: {
titleName () {
return this.$store.state.name
}
},
作用:帮助我们生成计算属性
import { mapState } from 'vuex'
computed: {
titleName () {
return this.$store.state.name
},
...mapState(['name', 'url'])
},
注意:建议仅将全局使用的属性放入 state,局部变量或组件级变量还是放入局部或组件作用域中。
store 的 computed 可以接受两个参数:state、getters:
getters: {
countAdd: (state, getters) => (num) => {
return state.count + num
},
countRise: (state, gettters) => (num) => {
return state.count * num + gettters.countAdd(5)
}
},
import { mapGetters } from 'vuex'
//默认名称
...mapGetters(['countAdd', 'countRise']),
//自定义名称
...mapGetters({
myRise: 'countRise'
})
store.commit('mutationFunc')
payload(state,option):
state为要改变的state对象,option为参数对象(负载对象)
//定义
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
//调用
store.commit('increment', {
amount: 10
})
建议: 使用常量替代 Mutation 事件类型
mutations: {
SOME_MUTATION_1 (state, options) {
//...
}
SOME_MUTATION_2 (state, options) {
//...
}
}
注意: Mutation 必须是同步函数
提交mutations:
this.$store.commit('SOME_MUTATION_1')
import { mapMutations } from 'vuex'
//methods
methods: {
//注册
...mapMutations(['CHANGE_NAME']),
//按钮点击
btnClick: function () {
this.CHANGE_NAME({ name: 'newName' })
}
}
Action(译:行动):
store.dispatch
方法触发:this.$store.dispatch('changeNameAction', { name: 'XXX' })
import { mapActions } from 'vuex'
...mapActions(['changeNameAction']),
this.changeNameAction({ name: 'WTF' })
actionA: ({ commit }, option) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('CHANGE_NAME', option)
console.log('运行了actionA')
resolve()
}, 3000)
})
},
actionB: ({ commit }, option) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('CHANGE_NAME', option)
console.log('运行了actionB')
resolve()
}, 5000)
})
},
actionC: async ({ commit, dispatch }, option) => {
await dispatch('actionA', option)
await dispatch('actionC', { name: 'CCC' })
}
...mapActions(['actionC']),
this.actionC({ name: 'AAA' })
//结果?
Modules
作用:store为单一对象,内容过多,影响执行效率及代码量过多 解决:分包(模块) 1.创建modules目录,以业务区分不同文件进行模块划分
src
|__store
|__index.js
|__modules
|__sectionA.js
|__sectionB.js
|__sectionC.js
|__...
2.store/index.js中modules引入
import sectionA from './modules/sectionA'
import sectionB from './modules/sectionB'
import sectionC from './modules/sectionC'
export default new Vuex.Store({
modules: {
sectionA,
sectionB,
sectionC
},
})
store.registerModule('sectionA', {
// ...
})
store.registerModule(['sectionB','sectionC'], {
// ...
})
未经允许不得转载:w3h5 » Vue状态管理模式:Vuex入门教程