Vuex|Vuex 学习笔记

前言 学习vuex之前,我提出了3个疑问。Vuex 官网

  • vuex 是什么?
    官方文档解释:vuex 是一个专为 Vue.js 应用程序开发的状态管理模式
    通俗点讲就是把这个项目中需要多个地方或全局使用的状态集中管理起来。
  • 【Vuex|Vuex 学习笔记】vuex 应用场景是什么?
    举个栗子
    ①多个组件依赖一种状态。就是说这个状态一改变,其他依赖这个状态的组件都要跟着改变。如果是兄弟组件,使用传值的方式的话就比较麻烦。
    ②多个组件共用同一个请求的数据。我比较懒,又不想在多个组件写相同的请求,而且增加重复代码,怎么办?这时候vuex 就派上用场了。
    从以上两个栗子得出:需要集中管理共同状态的都可以使用 vuex(不要滥用)
  • vuex 怎么用?
// store.js import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export default new Vuex.store({ state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... }, modules: { ... } })

// index.js import Vue from 'vue'; import store from '/store'; new Vue({ // 全局挂载 Vuex store })

在真正使用之前,你要了解 vuex 扩展的几个核心概念。
Vuex 核心概念 第一次看官方文档的时候,对下面几个概念不是很理解,认真看文档,换个理解方式就好多了。
  • state:管理状态的地方;可以类比成 vue 里面的 data
    注意:state(状态) 不能像 data 的属性那样通过赋值改变,只能通过 mutations 改变,这样的目的是为了更好地追踪状态的变化
export default new Vuex.Store({ state: { count: 1, ... } })

  • mutations:改变state(状态)的地方;可以类比成 vue 里面的 methods
    mutations 里面所有 回调函数 接受的第一个参数是 state,其余参数是commit传的。
    注意:mutations 是同步触发的,无法监听回调函数中进行的状态的改变;那我要写异步请求改变状态怎么办,actions 才是干这事的。
export default new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 改变状态;也就是修改 state 里面 count 的值 state.count++ } } })

那怎么调用mutations方法改变state?通过commit(提交)的方式。
// ... mutations: { increment (state, n) { state.count += n }, increment1 (state, params) { state.count += params.amount } }

// ***.vue // 普通方式提交 this.$store.commit('increment', 10) // 以对象形式提交 this.$store.commit({ type: 'increment1', amount: 10 })

  • actions:类似于 mutation,但不同的是①actions提交的是 mutation,而不是直接改变state; ②actions可以包含任意异步操作。
    actions 接受的第一个参数是 Store实例具有相同方法和属性的 context 对象,其余参数是dispatch分发的
export default new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { incrementAsync(context) { context.commit('increment') }, // 参数解构 incrementAsync1 ({ commit, getters }, params) { commit('increment') }, // 回调方式提交 incrementAsync2 ({ commit, getters }, params) { setTimeout(() => { commit('increment') }, 1000) } } })

那怎么调用actions的方法? 通过dispatch(分发)的方式。
// 以普通方式分发 this.$store.dispatch('incrementAsync')// 以载荷形式分发 this.$store.dispatch('incrementAsync1', { amount: 10 })// 以对象形式分发 this.$store.dispatch({ type: 'incrementAsync2', amount: 10 })

  • getters:可以看做是Store实例的计算属性;用法与vue 的计算属性一致。
    getters 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
    getters 只接受两个参数 stategetters。要是实现给 getter 传参,只能通过让 getter 返回一个函数。
export default 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) }, // 接收两个参数 doneTodos1: (state, getters) => { return getters.doneTodos.length }, // 返回一个函数 doneTodos2: (state) => (id) => { return state.todos.find(todo => todo.id === id) } } })

调用 getters
注意:getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。
// 通过属性调用 this.$store.getters.doneTodos1 // 通过方法调用 this.$store.getters.doneTodos2(1)

  • modules:模块的意思;每个模块拥有自己的 statemutationactionsgetters、甚至是嵌套子模块。
    当项目非常复杂时候,将 Store 分割成多个module(模块)管理的话维护起来就方便多了。
// ... export default new Vuex.Store({ modules: { moduleA, moduleB } })

总结
  • 如果认真看完就会发现与官网给的核心概念的目录顺序不同,我建议看文档的顺序是先看 statemutationactions,然后再看 gettersmodules,这样相对容易理解。
  • 详情请移步 Vuex 官网

    推荐阅读