持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情
Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex可以保证数据可追踪,同时不同组件之间可以共享数据。
Vuex的核心概念
Vuex 的五个核心概念:
- state : 单一状态树
- mutation: 数据管家(同步更改 state 里面的数据)
- action : 异步请求
- getter : 计算属性
- mudule: 模块管理
创建Vuex
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
getters: {},
modules: {}
})
引入Vuex
// main.js
import store from '@/store'
new Vue({
store,
render: h =>(App)
}).$mouted('#app')
使用
State
state 是唯一的公共数据源,可以将需要共享的数据统一放到store的state进行储存,类似于统一存储的数据data。
state是响应式的, 只要state值变化, 页面上使用的地方会自动更新同步
const store = new Vuex.Store({
state: {
count: 100
},
})
使用方法
- 组件中直接使用
this.$store.state.count或者$store.state.count<script> computed: { getCount() { return this.$store.state.count } } </script> <p>{{getCount}}</p> <p>$store.state.count</p> - 映射
<script> import { mapState } from 'vuex' export default{ computed: { // 数组映射 ...mapState(['count','state里面的变量名']) } } </script>
Mutation
mutations类似数据管家, 可以操作state里的数据,同时是唯一能修改state的地方。
mutations函数内, 只能写同步代码(同步函数), 确保调试工具可以追踪变化过程,因为调试工具要立刻产生一次记录, 所以必须是同步的
Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type) 和一个回调函数 (handler) 。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
const store = new Vuex.Store({
state: {
count: 100 // 库存
},
mutations: {
addCount (state, payload) { // 负责增加库存的管家
state.count += payload
}
}
})
使用
- 直接使用
this.$store.commit('mutations中的方法名',载荷值) - 映射使用
methods: { ...mapMutations(['addCount','mutations中的方法名']), add() { // 直接使用 this.$store.commit('addCount',1) // 映射后使用 this.addCount(1) } } }
Action
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
const store = new Vuex.Store({
// ...省略state和mutations此处
actions: {
asyncAddCount(store, payload){
setTimeout(() => { // 1秒后, 异步提交给add的mutations
store.commit('addCount', payload)
}, 1000)
},
asyncSubCount(store, payload) {
setTimeout(() => { // 1秒后, 异步提交给sub的mutations
store.commit('subCount', payload)
}, 1000)
}
}
})
使用
- 直接使用
this.$store.dispatch('actions中的函数名', 载荷值) this.$store.dispatch('asyncAddCount',10) // 载荷值可选 - 映射使用
import { mapActions } from 'vuex' export default { methods: { // 2. 把actions里方法映射到原地 ...mapActions(['asyncAddCount','actions里的函数名']) } }
Getter
vuex里的计算属性, 属于全局计算属性, 类似于vue中的computed,主要是进行缓存,对于Store中的数据进行加工处理形成新的数据
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos (state) {
return state.todos.filter(todo => todo.done)
}
}
})
使用
- 直接使用
this.$store.getters.计算属性名 this.$store.getters.doneTodos - 映射使用
import { mapGetters } from 'vuex' export default { computed: { ...mapGetters(['doneTodos','getters里的计算属性名']) } }
Module
-
为什么分模块?
集中式管理项目过大, 变量过多, 会导致state臃肿, 难以维护
-
如何分模块?
定义模块对象, state变成函数返回对象形式, 每个模块都有state/mutations/actions/getters/modules
-
根store如何注册?
modules里 { 模块名: 模块对象 }
// 写法
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = createStore({
modules: {
a: moduleA,
b: moduleB
}
})
// 访问
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
// 注意:在某个模块中actions里,state是局部状态,根节点状态是rootState
const moduleA = {
// ...
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}
总结
-
全局单例模式管理只有一个模块
-
mutations和actions的区别:
mutations是异步操作,actions是同步操作。
如果要修改state值,只能通过mutations,actions只能通过提交actions修改state