vuex(状态管理模式)
-
核心: store(仓库)
- state: 状态
- getters: 对 state 的派生,可以理解为 store 的计算属性
- mutaions: 修改 state 的唯一操作就是提交 mutaion 。
- actions: 类似于 mutaion , 用来处理异步。
- modules: 对仓库 分割成 模块
mapState(): sate的辅助函数是写在computed里面
mapGetters(): getters的辅助函数也是写在computed里面
mapMutations(): mutations的辅助函数是写在methods里面
mapActions(): actions的辅助函数也是写在methods里面
vuex的操作流程
- 先要有仓库,将我们项目中组件上需要共享的数据放置到我们 仓库中 state 的位置。
- 组件要使用 仓库 中 state 的数据,就从仓库里面拿出来用。
- 要修改仓库中 state 的数据
3.1 . commit(提交) mutation
3.2 . dispath(派发) action -> commit mutation - 然后仓库中 state 数据发生变化,组件就会得到更新
只有mutation才能修改厂库中的数据
vuex 的使用
- 安装 vuex (也可以在创建项目的时候选择vuex)
npm install --save vuex
- 项目中 src/store/index.js 文件中创建仓库的实例对象
// 1、引入 vue
import Vue from 'vue';
// 2、引入 vuex
import Vuex from 'vuex';
// 3、调用 Vuex
Vue.use(Vuex);
// 4.创建仓库的实例对象
const store = new Vuex.Store({
// 仓库的选项对象
})
// 5、暴露 store
export default store;
- 要 main.js new Vue 的地方配置一个 store 的选项。选项的值就是 2 中 仓库实例对象
如何将仓库中的数据拿到组件中去使用
使用vuex,就会在vue原型上添加router,store 就是仓库的实例对象
- 直接使用 this.$store 的方式在组件 template 模板中使用 (不推荐)
- 组件中使用 计算属性 去拿 仓库的数据
computed: { title () { return this.$store.state.title } }
- 借助 vuex 提供的辅助函数 mapState
mapState([]) - 组件的computed 的 key 必须要跟仓库中 state 里面某个key 相同
computed: mapState(['title'])
mapState({ }) - 组件的computed 的 key 可以自定义。
computed: mapState({
// 箭头函数可使代码更简练
// page1Title: state => state.title
// 传字符串参数 'count' 等同于 `state => state.count`
// page1Title: 'title'
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
page1Title (state) {
return state.title
}
})
- 将 mapState 与 组件自身的 computed 结合 (推荐); ...运算符是展开运算符,可以把对象或者数组内的数据展开(就是去掉括号的意思)
computed: {
...mapState(['title']),
firstName () {
return this.name.split('')[0]
}
},
如何修改仓库中的数据
- 先需要在仓库中定义我们的mutation
- 在组件中提交这个mutaion
2.1. this.store.commit({
type: mutaion的名字,
其余的参数
})
2.3. mapMutations 辅助函数 - mutation必须是同步函数,任何在回调函数中进行的状态的改变都是不可追踪的。
如何写异步代码在仓库中 actions
- 每一个action里面都可以写异步代码,但是action并不能修改state中的数据,真正修改数据的还是 mutaction
- 在组件中如何派发这个action
1- this.$store.dispatch('action的名字')
2- mapActions 辅助函数
命名空间
如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名
操作方便
- mapState(['todos']) 根仓库上拿toods
- mapState('todo', ['todos']) // 相当于this.$store.state.todo.todos
- mapGetters('todo', ['todos']) // 相当于this.$store.getters.todo.todos
如果 不带命名空间会造成什么影响
- getters 是全局的, 如果在多个模块中有重名的 getter 会报错
- mutations, actions 有重名的话,会都被执行
在带命名空间的模块内访问全局内容
1、rootState 和 rootGetters 可以拿到根上所有的state和getters。
2、若需要在全局命名空间内分发 action 或提交 mutation,将 { root: true } 作为第三参数传给 dispatch 或 commit 即可。dispatch和commit只能子模块提交或派发给根,不能提交给兄弟模块。
actions: {
fn2 ({ state, rootState, getters, rootGetters, commit, dispatch }) {
// console.log(state.name) // 获取自身的name
// console.log(rootState.b.name) // 获取b上的name
// console.log(getters.firstName) // 获取自身的firstName
// console.log(rootGetters['b/firstName']) // 获取b上的firstName
// commit('fn3') // 提交给自身mutations的fn3
// commit('fn3', '123', { root: true }) // 提交给根上mutations的fn3
dispatch('fn4', null, { root: true }) // 派发给根上mutations的fn3
}
}