推荐: ------ Vuex官方文档 -----

  1. Vuex是什么
    Vuex是一个专门为Vue.js应用程序开发的状态管理模式.
    简单来说: 应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏
    ● 多个视图依赖于同一状态
    ● 来自不同视图的行为需要变更同一状态
    即Vuex提供了管理多个视图能够使用的共享状态
  2. 基本使用
    每一个Vuex应用的核心就是store(仓库)
    “store” 基本就是一个容器,它包含着你的应用中大部分的状态
    Vuex和单纯的全局对象有一下两点不同:
    (1) Vuex的状态存储是响应式的. 当Vue组件从store中读取状态的时候,若store中的状态发生变化,name相应的组件也会相应的得到高效更新
    (2) 不能直接改变store中的状态. 改变store中的状态的唯一途径就是提交(commit)mutation. 这样使得我们可以方便的跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好的了解我们的应用
    ------------ 基本实例 -----------
new Vue({
   
  el: "#app",
  store
})

store 文件夹中的index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const state = new Vuex.Store({
   
  // 1. store 中状态state
  state: {
   
    count: 0
  },
  // 2. 通过mutation实现state中的状态变更
  mutation: {
   
    // 第一参数传入state
    increment(state) {
   
      state.count++
    }
  }
})

从组件中通过store.state 获取状态对象,通过store.commit 方法触发状态变更

<script>
export default {
   
  data() {
   
    return {
   
      // 本组件count 中绑定store中count
      count: this.$store.state.count
    }
  },
  methods: {
   
     increment() {
   
       this.$store.commit('increment')
       console.log(this.count)   // 1
     }
  },
}
</script>

核心概念


State

const store = new Vuex.Store({
   
  state: {
   
    count: 1
  }
})

组件中访问

this.$store.state.count

Getters
getters可以认为是store中的计算属性,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖发生了改变才会被重新计算
Getter接受state作为其第一个参数

const store = new Vuex.Store({
   
  state: {
   
    todos: [
      {
    id: 1, text: '..', done: true},
      {
    id: 2, text: '..', done: false}
    ]
  },
  getters: {
   
    doneTodos: state => {
   
      // filter: 迭代数组,过滤出符合条件的数组返回一个新的数组
      return state.todos.filter(todo => todo.done)
    }
  }
})

通过属性访问
Getter 会暴露为 store.getters 对象.可以以属性形式访问这些值

this.$store.getters.doneTodos // [{
    id: 1, text: '..', done: true}]

Getter 也可以接受其他getter作为第二个参数:

getters: {
   
  doneTodosCount: (state,getters) => {
   
    return getters.doneTodos.length
  }
}
this.store.getters.doneTodosCount  // 1

注意: getter 在通过属性访问时是作为Vue的响应式系统的一部分缓存其中的
通过方法访问
你也可以通过让getter返回一个函数,来实现getter传参

getters: {
   
  getTodoById: (state) => (id) => {
   
    return state.todos.find(todo => todo.id === id)
  }
}
this.$store.getters.getTodoById(2)   // {
    id: 2, text: '..', done: false}

注意: getter在通过方法访问时,每次都会去进行调用,而不会缓存结果


Mutations
更改Vuex的store中的状态唯一方法就是提交mutation
每个mutation都有一个字符串的时间类型和一个回调函数

const store = new Vuex.Store({
   
  state: {
   
    count: 1 
  },
  mutation: {
   
    increment(state) {
   
      //变更状态
      state.count++
    }
  }
})

调用方法

this.$store.commit('increment')

提交载荷(Payload)
可以向store.commit 传入额外的参数,即mutation 的载荷(payload)

 //...
 mutations: {
   
   increment(state, payload) {
   
     state.count += payload.amount
   }
 }
this.$store.commit('increment', {
   
  amount: 10
})

Mutation 需遵守Vue 的响应规则

Vuex中mutation的一些注意事项:
(1) 最好提前在store中初始化好所有所需属性
(2) mutation必须是同步函数
(3) 当需要在对象上添加新属性时,应该
使用 Vue.set(obj, ‘newProp’, 123),或者
(4) 以新对象替换老对象.例如利用对象展开运算符

 //...
   state: {
   
     obj: {
   
       name: 'lzy',
       age: 17
     }
   }
 }
 state.obj = {
    ...state.obj, newProp: 123}
 console.log(state.obj)  // {
   name: 'lzy', age: 17, newProp: 123}
 /**
 对象展开运算符(...)
 可以将一个数组或者对象进行展开
 例如: let obj = {
   x:1 , y:2}
      let aa = {
   ...obj, z: 3} // {
   x:1 , y:2, z:3}
      let obj2 = [1,2,3]
      console.log(..obj)  // 1 2 3
 **/

mapMutations 辅助函数映射

import {
    mapMutations } from 'vuex'

export default {
   
  // ...
  methods: {
   
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`

      // `mapMutations` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
    ]),
    ...mapMutations({
   
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
  }
}

Actions
Action类似于mutation,不同在于
● Action提交的是mutation,而不是直接变更状态
● Action可以包含任意一部操作
基本案例

const store = new Vuex.Store({
   
  state: {
   
    count: 0
  },
  mutation: {
   
    increment (state) {
   
      state.count++
    }
  },
  actions: {
   
    incrementAsync ({
    commit }) {
   
      setTimeOut(() => {
   
        commit('increment')
      },1000)
    }
  }
})

在组件中分发Action
在组件中使用this.$store.dispath(‘xxx’)分发action
或者使用mapAction 辅助函数将组件的method 映射为 store.dispath调用

import  {
    mapAction } from 'vuex'

export default {
   
  //...
  method: {
   
    // 辅助函数映射调用
    ...mapActions({
   
      add: 'increment'  // 将`this.add()` 映射为`this.$store.dispatch('incrementAsync')`
    })
    // 直接调用
    addAction() {
   
      this.$store.dispatch('incrementAsync')
    },
    
  }
}

Modules
Vuex允许我们将store 分割成模块(Module)
每一个模块拥有自己的state,mutation,action.getter甚至嵌套子模块

const moduleA = {
   
  state: () => ({
   
    name: 'lzy',
    count: 0
  }),
  mutations: {
   
    increment (state) {
   
      //这里'state'对象是模块的局部状态
      state.count++
    }
  },
  actions: {
    ... },
  getters: {
   
    sumWithRootCount(state, getters, rootState) {
   
      // rootState根节点状态作为第三个参数暴露出来
      return state.count + rootState.count
    }
}

const moduleB = {
   
  state: () => ({
   ...}),
  mutations: {
   ...},
  actions: {
   ...}
}

const store = new Vuex.Store({
   
  state: {
   
    count
  },
  modules: {
   
    a: moduleA,
    b: moduleB
  }
})

在组件中调用module状态

// moduleA中的状态
this.$store.state.a.name