[关闭]
@xiaoqq 2016-10-26T07:02:10.000000Z 字数 2994 阅读 2037

Vue学习笔记——Vuex

Vue


一、什么是Vuex

定义:Vuex 是一个专门为 Vue.js 应用所设计的集中式状态管理架构

为什么使用Vuex?

单独使用Vue.js时,通常会把状态储存在组件的内部。对于对个组件共享状态的情况,我们通常使用事件来进行传递。这在小型系统中比较简单,但是在大中型系统中事件流会变得非常复杂

为了更好的解决在大型应用中状态的共用问题,我们需要对组件的 组件本地状态(component local state)应用层级状态(application level state) 进行区分。应用级的状态不属于任何特定的组件,但每一个组件仍然可以监视(Observe)其变化从而响应式地更新 DOM。通过汇总应用的状态管理于一处,我们就不必到处传递事件。因为任何牵扯到一个以上组件的逻辑,都应该写在这里。此外,这样做也能让我们更容易地记录并观察状态的变更(Mutation,原意为突变),甚至可以实现出华丽如时光旅行一般的调试效果。

二、开始使用Vuex

每一个 Vuex 应用的核心就是 store(仓库)。"store" 基本上就是一个容器,它包含着你应用里大部分的 状态(即state).

所以:Vuex == 全局对象?
两者并不完全相等,Vue与全局对象有两点不同:

  1. 当store中状态发生变化,相应的组件也会得到更新;
  2. 不能直接改变store的状态,改变 store 中的状态的唯一途径就是显式地分发 状态变更事件(explicitly dispatching mutations)。

简易例子

首先,初始化state变量和mutations

  1. import Vuex from 'vuex'
  2. const state = {
  3. count: 0
  4. }
  5. const mutations = {
  6. INCREMENT (state) {
  7. state.count++
  8. }
  9. }
  10. export default new Vuex.Store({
  11. state,
  12. mutations
  13. })

然后,可以通过store.state 来读取 state 对象,还可以通过 dispatch 某 mutation 的名字来触发这些状态变更:

  1. store.dispatch('INCREMENT')
  2. console.log(store.state.count) // -> 1

一定要注意:我们是通过分发变更(mutation)的方式来改变state中的状态,而不是直接变更。

三、核心概念

Vuex的核心概念一共有三点:State(状态)、Mutations(变更) 和 Actions(动作)

1.数据流:

1)  用户在组件中的输入操作触发 action 调用;

2)  Actions 通过dipatch(分发) mutations 来修改 store 实例的状态;

3)  Store 实例的状态变化反过来又通过 getters 被组件获知。


图1. Vuex中数据流示意图

2. State 和 Getters

Vuex 使用单一状态树,即用一个对象就包含了全部的应用层级状态。(每个应用仅仅只包括一个store实例)

Vue组件获取Vuex状态

  1. 安装 Vuex 并且将您的根组件引入 store 实例:

    1. import Vue from 'vue'
    2. import Vuex from 'vuex'
    3. import store from './store'
    4. import MyComponent from './MyComponent'
    5. // 关键点,教 Vue 组件如何处理与 Vuex 相关的选项
    6. Vue.use(Vuex)
    7. var app = new Vue({
    8. el: '#app',
    9. // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
    10. store, // 译注:简写,等效于 store: store
    11. components: {
    12. MyComponent
    13. }
    14. })
  2. 在子组件中,通过在 vuex.getters 选项里定义的 getter 方法来读取状态:

    1. // MyComponent.js
    2. export default {
    3. template: '...',
    4. data () { ... },
    5. // 此处为我们从 store 实例中取回状态的位置
    6. vuex: {
    7. getters: {
    8. // 该 getter 函数将会把仓库的 `store.state.count` 绑定为组件的 `this.count`
    9. count: state => state.count
    10. }
    11. }
    12. }

Getters函数使用要点

  1. getter 函数必须是纯函数,所以,在 getter 里不能依赖 this 关键字;

  2. getter 函数可以返回派生状态。Vuex 状态的 getters 内部其实就是计算属性,这就意味着你能够以响应式的方式(并且更高效)地计算派生属性;

    1. vuex: {
    2. getters: {
    3. filteredMessages: state => {
    4. return state.messages.filter(message => {
    5. return message.threadID === state.currentThreadID
    6. })
    7. }
    8. }
    9. }
  3. 可以在多组件中共享 getter 函数,这样做还可以提高运行效率;

  4. 组件永远都不应该直接改变 Vuex store 的状态,组件唯一能影响全局状态的方法就是想办法触发 mutations。

三、Mutations

Mutations 本质上是一个事件系统:每个 mutation 都有一个 事件名 (name) 和 一个 回调函数
(handler)。

任何一个 Mutation handler 的第一个参数永远为所属 store 的整个 state 对象:

  1. import Vuex from 'vuex'
  2. const store = new Vuex.Store({
  3. state: {
  4. count: 1
  5. },
  6. mutations: {
  7. INCREMENT (state) {
  8. // 改变 state
  9. state.count++
  10. }
  11. }
  12. })

用全部大写命名 mutation 是一个惯例,方便将它和 actions 区分开。

触发mutation:store.dispatch('INCREMENT')

mutation有一点很重要就是它必须是同步函数,因为在mutation 中混合异步调用会程序很难调试。所以,所有的同步调用都放在mutation中,异步调用放在Actions中

四、Actions

Actions 是用于分发 mutations 的函数

Vuex actions 的第一个参数是 store 实例,附加上可选的自定义参数:

  1. // 最简单的 action
  2. function increment (store) {
  3. store.dispatch('INCREMENT')
  4. }
  5. // 带附加参数的 action
  6. // 使用 ES2015 参数解构
  7. function incrementBy ({ dispatch }, amount) {
  8. dispatch('INCREMENT', amount)
  9. }

在组件中使用Actions:

  1. // 组件内部
  2. import { incrementBy } from './actions'
  3. const vm = new Vue({
  4. vuex: {
  5. getters: { ... }, // state getters
  6. actions: {
  7. incrementBy // ES6 同名对象字面量缩写
  8. }
  9. }
  10. })

五、使用规则

  1. 应用 state 存在于单个对象中;
  2. 只有 mutation handlers 可以改变 state;
  3. Mutations 必须是同步的,它们做的应该仅仅是改变 state;
  4. 所有类似数据获取的异步操作细节都应封装在 actions 里面。
  5. 组件通过 getters 从 store 中获取 state,并通过调用 actions 来改变 state。
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注