Vuex

125 阅读3分钟

五. Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。简单的讲就是把需要多个组件共享的变量全部存储在一个对象里面。

  • 它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
  • Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

1.1. 单界面的状态管理

image.png

1.2. Vuex状态管理图例

image.png

1.3. Vuex核心的概念

  • State

    State单一状态树
    
    State: {
      count: 0
    }
    
  • Getters

    /* 
    就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
    
    getters默认是不能传递参数的, 如果希望传递参数, 那么只能让getters本身返回另一个函数 */
    
    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)
        }
      }
    })
    
  • Mutation

    Vuex的store状态的更新唯一方式:提交Mutation
    Mutation主要包括两部分:
    	1.字符串的事件类型(type)
    	2.一个回调函数(handler),该回调函数的第一个参数就是state。
    
    mutation的定义方式
    mutations: {
      increment(state){
       state.count++
      }
    }
    
    通过mutation更新
    increment(){
      this.$store.commit('increment')
    }
    
    在通过mutation更新数据的时候, 有可能我们希望携带一些额外的参数
    参数被称为是mutation的载荷(Payload)
    
    Mutation响应规则
    当给state中的对象添加新属性时, 使用下面的方式更新数据:
    方式一: 使用Vue.set(obj, 'newProp', 123)
    方式二: 用心对象给旧对象重新赋值
    
    Mutation常量类型 – 概念
    使用常量替代Mutation事件的类型.
    
    
    通常情况下, 不要再mutation中进行异步的操作
    主要的原因是当我们使用devtools时, 可以devtools可以帮助我们捕捉mutation的快照.
    
  • Action

    /* Action类似于Mutation, 但是是用来代替Mutation进行异步操作的.
    
    在Vue组件中, 如果我们调用action中的方法, 那么就需要使用dispatch,同样的, 也是支持传递payload
    
    */
    
    mutations: {
      increment(state){
       state.count++
      }
    },
    actions: {
      increment(context,payload) {
        setTimeout(()=>{
          context.commit('increment', payload)
        }, 3000)
      }
    }
    
    
  • Module

    /* 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
    
    为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
    */
    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 的状态
    

1.4. 项目结构

├── index.html
├── main.js
├── api
│   └── ... # 抽取出API请求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块