7

Vuex 入门

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。说白了,vuex就是用来管理数据的。

直接下载或者CDN引入

https://unpkg.com/vuex

Vuex的核心就是store(仓库),其包含应用中的大部分状态。Vuex 和单纯的全局对象有以下两点不同:

  • Vuex的状态存储时响应式的
  • store中状态不能直接改变

现在我们来创建一个store:

new Vuex.Store({
    state:{
        //......
    },
    mutations:{

    }
})

在这个store里,包含了一个 state 对象和 mutations

state用来存储初始化的数据,读取数据使用 store.state.数据 。

修改数据使用 mutations ,调用 mutations 里的数据需要使用 commit()

现在来尝试使用以下vuex,做一个简单的计数程序:

HTML

  <div id="app">

  </div>

  <template id="tpl">
    <div>
      <tip></tip>
      <btn></btn>
    </div>
  </template>

javascript


    var store = new Vuex.Store({
      state:{
        count:0
      },
      mutations:{
        plus(state){
          state.count++
        },
        less(state){
          state.count--
        }
      }
    });

    var app=new Vue({
      el:'#app',
      template:'#tpl',
      components:{
        tip:{
          template:'<div>{{$store.state.count}}</div>'
        },
        btn:{
          template:`
            <div>
              <input type="button" value="+" v-on:click="$store.commit('plus')"/>
              <input type="button" value="-" v-on:click="$store.commit('less')"/>
            </div>
          `
        }
      },
      store
    }}

vuex的核心

  • State
  • Getters
  • Mutations
  • Actions
  • Modlues

State

由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:

// 创建一个 Counter 组件
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。

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
    }
  })
}

Getters

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

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

如果有多个组件需要用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入它 —— 无论哪种方式都不是很理想。

Vuex 允许我们在 store 中定义『getters』(可以认为是 store 的计算属性)。就像计算属性一样,getters的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

Getters 接受 state 作为其第一个参数:

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)
    }
  }
})


store.getters.doneTodes

Getters 也可以接受其他 getters 作为第二个参数:

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

store.getters.doneTodosCount

我们可以很容易地在任何组件中使用它:

computed: {
  doneTodosCount () {
    return this.$store.getters.doneTodosCount
  }
}
mapGetters 辅助函数

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

computed:{
  ...mapGetters([
    // 使用对象展开运算符将 getters 混入 computed 对象中
    'doneTodosCount',
    'anotherGetters'
  ])
}

Mutations

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


const store = new Vuex.Store({
  state:{
    count:0
  },
  mutations:{
    plus(state){
      state.count++
    },
    less(state){
      state.count--
    }
  }
});

提交载荷(Paylaod)

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

const store = new Vuex.Store({
  state:{
    count:0
  },
  mutations:{
    plus(state,n){
      state.count+=n
    },
    less(state,n){
      state.count-=n
    }
  }
});

this.$store.commit('plus',5)
this.$store.commit('less',5)

Actions

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation ,而不是直接变更状态
  • Action 可以包含任意异步操作
actions:{
  plus(commit){
    commit({type:'plus',n:5})
  }
}

PureView
440 声望28 粉丝