Vuex的使用及原理

1、Vuex 是什么?

在理解Vuex的使用和原理以前首先要知道Vuex是什么?按照官方的说法,Vuex是专门为Vuejs应用程序设计的一款状态管理模式,相似于React中的Redux。它采用集中式存储管理应用的全部组件的状态。前端

一、 Vuex的构成

下面图片很清晰的展现出了Vuex的组成结构vue

  • state

state 是 Vuex 的数据中心,也就是说state是用来存储数据的。vuex

  • Getters

getters 和 组件的 computed 相似,方便直接生成一些能够直接用的数据。当组装的数据要在多个页面使用时,就可使用 getters 来作。npm

  • Mutations

mutations提交更改数据,使用store.commit方法更改state存储的状态。数组

  • Actions

Action 提交的是 mutation,而不是直接变动状态。Action 能够包含任意异步操做。缓存

二、Vuex的使用方式

  • 安装Vuex

    方式一: npm 方式
    npm install vuex --save
    复制代码
    方式二: yarn 方式
    yarn add vuex
    复制代码
  • 在应用中引入Vuex

import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)   
复制代码
  • 在 Vue 组件中得到 Vuex 状态(State)

    方式一: this.$store.state获取bash

    经过在根实例中注册 store 选项,该 store 实例会注入到根组件下的全部子组件中,且子组件能经过 this.$store 访问到异步

    const Counter = {
            template: `<div>{{ count }}</div>`,
            computed: {
                count () {
                    return this.$store.state.count
                }
            }
        }
    复制代码

    方式二: mapState 辅助函数获取(推荐)函数

    当一个组件须要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,咱们可使用 mapState 辅助函数帮助咱们生成计算属性,让你少按几回键:ui

    import { mapState } from "vuex";
        export default {
        // ...
        computed: mapState({
            // 箭头函数可以使代码更简练
            count: state => state.count,
    
            // 传字符串参数 'count' 等同于 `state => state.count`
            countAlias: 'count',
    
            // 为了可以使用 `this` 获取局部状态,必须使用常规函数
            countPlusLocalState (state) {
                return state.count + this.localCount
            }
        })
    }
    复制代码

    当映射的计算属性的名称与 state 的子节点名称相同时,咱们也能够给 mapState 传一个字符串数组。

    computed: mapState([
            // 映射 this.count 为 store.state.count
            'count'
        ])
    复制代码
  • Getter的获取方式

    有时候咱们须要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:

    computed: {
            doneTodosCount () {
                return this.$store.state.todos.filter(todo => todo.done).length
            } 
        }
    复制代码

    若是有多个组件须要用到此属性,咱们要么复制这个函数,或者抽取到一个共享函数而后在多处导入它——不管哪一种方式都不是很理想。
    Vuex 容许咱们在 store 中定义“getter”(能够认为是 store 的计算属性)。就像计算属性同样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被从新计算。

    方式一: 经过属性访问

    store.getters.doneTodos
    复制代码

    方式二: 经过方法访问

    你也能够经过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查询时很是有用。

    getters: {
         // ...
         getTodoById: (state) => (id) => {
           return state.todos.find(todo => todo.id === id)
         }
       }
    复制代码
    store.getters.getTodoById(2)
    复制代码

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

    方式三: mapGetters 辅助函数获取(推荐)

    import { mapGetters } from 'vuex'
    
        export default {
          // ...
          computed: {
          // 使用对象展开运算符将 getter 混入 computed 对象中
            ...mapGetters([
              'doneTodosCount',
              'anotherGetter',
              // ...
            ])
          }
        }
    复制代码

    若是你想将一个 getter 属性另取一个名字,使用对象形式:

    mapGetters({
          // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
          doneCount: 'doneTodosCount'
        })
    复制代码
  • Mutation使用方式

    上面咱们说了更改 Vuex 的 store 中的状态的惟一方法是提交 mutation,Vuex 中的 mutation 很是相似于事件:每一个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是咱们实际进行状态更改的地方,而且它会接受 state 做为第一个参数。

    使用常量替代 Mutation 事件类型

    // mutation-types.js
        export const SOME_MUTATION = 'SOME_MUTATION'
    复制代码
    // store.js
        import Vuex from 'vuex'
        import { SOME_MUTATION } from './mutation-types'
        
        const store = new Vuex.Store({
          state: { ... },
          mutations: {
            // 咱们可使用 ES2015 风格的计算属性命名功能来使用一个常量做为函数名
            [SOME_MUTATION] (state) {
              // mutate state
            }
          }
        })
    复制代码

    固然使用常量代替Mutation事件类型也不是必须的,若是你不喜欢,你彻底能够不这样作。

    在组件中提交 Mutation

    你能够在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(须要在根节点注入 store)。

    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')`
            })
          }
        }
    复制代码
  • Action使用方式

    Action的注册

    Action 函数接受一个与 store 实例具备相同方法和属性的 context 对象,所以你能够调用 context.commit 提交一个 mutation,或者经过 context.state 和 context.getters 来获取 state 和 getters。当咱们在以后介绍到 Modules 时,你就知道 context 对象为何不是 store 实例自己了。

    const store = new Vuex.Store({
          state: {
            count: 0
          },
          mutations: {
            increment (state) {
              state.count++
            }
          },
          actions: {
            increment (context) {
              context.commit('increment')
            }
          }
        })
    复制代码

    分发 Action

    // 以载荷形式分发
        store.dispatch('incrementAsync', {
          amount: 10
        })
        
        // 以对象形式分发
        store.dispatch({
          type: 'incrementAsync',
          amount: 10
        })
    复制代码

    在组件中分发 Action

    你在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(须要先在根节点注入 store)

    import { mapActions } from 'vuex'
    
        export default {
          // ...
          methods: {
            ...mapActions([
              'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
        
              // `mapActions` 也支持载荷:
              'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
            ]),
            ...mapActions({
              add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
            })
          }
        }
    复制代码

    小结

    至此Vuex的使用及原理就介绍到这里,若是还有不一样理解的小伙伴们还请下发留言。若是有写的很差的地方还请多多指教。我会继续更新有关前端的技术文章的。

相关文章
相关标签/搜索