zoukankan      html  css  js  c++  java
  • vuex入门

    安装&使用

    npm install vuex --save
    • 1

    通过Vue.use()来使用:

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    • 1
    • 2
    • 3
    • 4

    Vuex是什么

    Vuex是一个专为vue.js应用程序开发的状态管理模式。它集中储存该应用的所有数据,统一保管。便于维护。

    核心概念


    state

    vuex使用单一状态树,也就是一个对象包含了整个应用的所有状态,它作为唯一的数据源。也就是说,每个应用仅有一个store实例。

    在Vue组件中获得Vuex状态

    Vuex用过store选项,提供了一种机制,将数据从跟组件注入到每个子组件中(需要调用Vue.use(Vuex)):

    import store from './store'
    
    new Vue({
      el: '#app',
      // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
      store,
      template: '<App/>',
      components: { App }
    })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    通过在根实例中注册store选项,该store实例会注入到根组件下的所有子组件中。且子组件能通过this.$store访问到:

    const Counter = {
      template: `<div>{{ count }}</div>`,
      //从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:
      computed: {
        count () {
          return this.$store.state.count
        }
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    mapState辅助函数

    当一个组件需要获取多个状态时,逐个声明计算属性会很麻烦,为此我们可以使用mapState辅助函数帮我们生成:

    // 在单独构建的版本中辅助函数为 Vuex.mapState
    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
        }
      })
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    上边我们给mapState传了一个对象,如果我们要生成的计算属性名称与state子节点名称相同时,也可以直接给mapState传入一个字符串数组:

    computed: mapState([
      // 映射 this.count 为 store.state.count
      'count'
    ])
    • 1
    • 2
    • 3
    • 4

    对象展开运算符

    mapState函数返回的是一个对象,但是一个组件中的计算属性,不仅有来自store的,还有它局部的。那么如何混用呢?我们使用对象展开运算符:

    computed: {
      //localComputed 是组件的局部计算属性
      localComputed () { /* ... */ },
      // 使用对象展开运算符将此对象混入到外部对象中
      ...mapState({
        // ...
      })
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    组件仍保有局部状态

    上边说了组件的局部状态,也就是只有这个组件自己需要用到的数据,比如模态框组件是否显示的状态,这个数据只对该组件本身有意义,所以不应该放入Vuex,作为局部状态,反而更利于维护。

    Getters

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

    computed: {
      doneTodosCount () {
        return this.$store.state.todos.filter(todo => todo.done).length
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5

    但如果我们要在多个组件中使用此属性,难道要复制这个函数吗?Vuex允许我们在store中定义getters(可以认为是store的计算属性)。getter接受state作为第一个参数:

    // 在'store/index.js'中
    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)
        },
        // getters也可以接受其他getters作为第二个参数
        doneTodosCount: (state, getters) => {
          return getters.doneTodos.length
        }
      }
    })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    getters会暴露为store.getters对象:

    store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
    • 1

    mapGetters辅助函数

    mapGetters辅助函数仅仅是将store中的getters映射到局部计算属性:

    import { mapGetters } from 'vuex'
    
    export default {
      // ...
      computed: {
      // 使用对象展开运算符将 getters 混入 computed 对象中
        ...mapGetters([
          'doneTodosCount',
          'anotherGetter',
          // ...
        ])
        //如果想给getter属性领取一个名字,可以对象形式:
        mapGetters({
          // 映射 this.doneCount 为 store.getters.doneTodosCount
          doneCount: 'doneTodosCount'
        })
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Mutations

    更改Vuex的store中的状态的唯一方法是提交mutation。Vuex的mutataions非常类似于事件:每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。这个回调函数就是我们实际进行状态更改的地方,他会接受state作为第一个参数:

    const store = new Vuex.Store({
      state: {
        count: 1
      },
      mutations: {
        increment (state) {
          // 变更状态
          state.count++
        }
      }
    })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    上边注册了一个类型为increment的mutation:“当触发一个类型为increment的mutation时,调用此函数。”实际使用时:store.commit('increment')

    提交载荷(Payload)

    载荷其实就是要传入vuex的数据对象啦。

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

    //注册mutation
    mutations: {
      // 这里的传入的数据对象payload就是载荷
      increment (state, payload) {
        state.count += payload.amount
      }
    }
    
    //调用mutation的handler
    store.commit('increment', {
      amount: 10
    })
    //还可以使用对象风格来调用
    store.commit({
      type: 'increment',
      amount: 10
    })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    Mutations需遵守Vuex的响应规则
    既然Vuex的store中的状态时响应式的,那么当我们变更状态时,监视状态的vue组件也会自动更新。所以同样要遵守vue的响应式注意事项:

    1. 最好提前在store中初始化好所有属性
    2. 当需要在对象上添加新属性时:1.用Vue.set;2.用新对象替换老对象。

    使用常量替代Mutation事件类型

    使用常量替代 mutation 事件类型在各种 Flux 实现中是很常见的模式。这样可以使 linter 之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个 app 包含的 mutation 一目了然:

    // mutation-types.js
    export const SOME_MUTATION = 'SOME_MUTATION'
    
    
    // store.js
    import Vuex from 'vuex'
    import * as types from './mutation-types'
    
    const store = new Vuex.Store({
      state: { ... },
      mutations: {
        // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
        [types.SOME_MUTATION] (state) {
          // mutate state
        }
      }
    })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    mutation必须是同步函数

    一条重要的原则就是要记住 mutation 必须是同步函数

    在组件中提交Mutations

    你可以在组件中使用this.store.commit('type')提交mutataion,或者使用mapMutations辅助函数将组件中的methods映射为store.commit调用(需要在根节点注入store)。

    import { mapMutations } from 'vuex'
    
    export default {
      // ...
      methods: {
        ...mapMutations([
          'increment' // 映射 this.increment() 为 this.$store.commit('increment')
        ]),
        ...mapMutations({
          add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
        })
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Actions

    Action类似于mutation,不同之处在于:

    • Action提交的是mutataion,而不是直接变更状态。
    • Action可以包含任意异步操作。

    注册一个简单的Action:

    const store = new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increment (state) {
          state.count++
        }
      },
      actions: {
        increment (context) {
          context.commit('increment')
        }
      }
    })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。当我们在之后介绍到 Modules 时,你就知道 context 对象为什么不是 store 实例本身了。

    解构:ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值。

    //例如:赋值  var [a,b,c] = [1,2,3]
    //例如:交换变量 [x,y] = [y,x]
    //例如:函数参数解构:
    // function add([x, y]){
    //   return x + y;
    // }
    // add([1, 2]); // 3
    
    
    //实践中我们常用到 参数解构 来简化代码,下边
    //的 { commit } 就用到了解构。
    
    actions: {
      increment ({ commit }) {
        commit('increment')
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    这里解构的对象是context对象,也就是说context <==> { commit },这样写就可以用commit替代context.commit,简化代码。

    分发Action

    Action通过store.dispatch方法触发:store.dispatch('increment')
    Actions 支持同样的载荷方式和对象方式进行分发:

    // 以载荷形式分发
    store.dispatch('incrementAsync', {
      amount: 10
    })
    
    // 以对象形式分发
    store.dispatch({
      type: 'incrementAsync',
      amount: 10
    })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    我们可以在Action内部执行异步操作:

    actions: {
      incrementAsync ({ commit }) {
        setTimeout(() => {
          commit('increment')
        }, 1000)
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在组件中分发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({
          add: 'increment' // 映射 this.add() 为 this.$store.dispatch('increment')
        })
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    组合Action

    Modules

    使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。

    为了解决以上问题,Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割:

    const moduleA = {
      state: { ... },
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    
    const moduleB = {
      state: { ... },
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        a: moduleA,
        b: moduleB
      }
    })
    
    store.state.a // -> moduleA 的状态
    store.state.b // -> moduleB 的状态
  • 相关阅读:
    win10快速搭建git服务
    java字节流转对象,应用于协议解析
    产品设计-后台管理权限设计RBAC
    Git :fatal: 错误提示解决办法
    初学git,出现错误:fatal: Not a git repository (or any of the parent directories): .git
    css 清除浮动
    asp.net连接SQL SERVER 2012的方法
    c#的序列化与反序列化
    .NET三层架构例子超链接可以点击显示内容页面
    ASP.NET中iframe框架点击左边页面链接,右边显示链接页面内容
  • 原文地址:https://www.cnblogs.com/pomelott/p/8376761.html
Copyright © 2011-2022 走看看