Vue状态管理-Vuex

构成

一个Vuex对象通常包括State, Getter, Mutation, Action这个几个属性。

const state = {}
const getters = {}
const mutations = {}
const actions = {}

export default new Vuex.Store({
    state,
    getters,
    mutations,
    actions
})

state是共享状态的集合,getters通过操作state获得派生状态,mutations是操作state数据的方法集合,actions让mutations中的方法能够在异步操作中起作用。


State: 状态

1. 声明
const state = {
    todos: [
        { id: 1, text: 'breakfast', done: true },
        { id: 2, text: 'basketball', done: false },
        { id: 3, text: 'reading', done: false },
    ],
    count: 0
}
2. 使用

Vuex中的状态存储是响应式的,读取Vuex状态一般用计算属性返回某个状态。比如:

computed: {
  todos() {
    return this.$store.state.todos;
  },
  count() {
    return this.$store.state.count;
  }
}
3. mapState

当有多个状态的时候,都声明为计算属性会显得冗余,我们可以通过mapState辅助函数来帮助我们生成计算属性。

import { mapState } from 'vuex'
export default {
  // ...
  computed: {
    ...mapState({
      todos: state => state.todos,
      count: state => state.count
    })
  }
}

import { mapState } from 'vuex'
export default {
  // ...
  computed: {
    ...mapState({
      todos: 'todos', // 后面加引号的'todos'指的是state中的todos
      count: 'count'
    })
  }
}

当计算属性名称与某个状态属性名相同时,可以简写为给mapState传一个字符串数组。比如:

import { mapState } from 'vuex'
export default {
  // ...
  computed: {
    ...mapState([
      'todos',
      'count'
    ])
  }
}

Getter: 派生状态

1. 声明

如果我们需要从状态中派生出一些状态,比如对列表进行过滤:

computed: {
  notTodos() {
    return this.$store.state.todos.filter(item => !item.done);
  }
}

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

// ...
const getters = {
    notTodos: state => state.todos.filter(item => !item.done)
}
// ...

getter还可以接收其他getter作为第二个参数:

const getters = {
    notTodos: state => state.todos.filter(item => !item.done),
    notTodosLength: (state, getters) => getters.notTodos.length
}
2. 使用

然后在计算属性中使用getters获取即可:

computed: {
  notTodos() {
    return this.$store.getters.notTodos;
  }
}
3. mapGetters

当有多个getter的时候,我们可以通过mapGetters辅助函数来帮助我们生成计算属性

computed: {
  ...mapGetters([
    'notTodos',
    'notTodosLength'
  ])
}

如果想给getter属性另取一个名字,可以使用对象形式

computed: {
  // ...
  ...mapGetters({
    notTodosList: 'notTodos',
    notTodosLength: 'notTodosLength'
  })
}

Mutation: 操作状态

注意:不建议在组件中直接对state进行操作,使用mutations来进行这些操作
mutation 必须是同步函数。

1. 声明

在mutations中定义一个addTodos方法:

const mutations = {
  addTodos: (state, todo) => {
    state.todos.push(todo);
  }
}
2. 使用

在vue文件中就可以通过store.commit来调用:

methods: {
  addTodos() {
    let todo = { id: 4, text: 'writing', done: false };
    this.$store.commit('addTodos', todo);
  }
}
3. mapMutations

同样,当有多个mutation的时候,我们可以通过mapMutations辅助函数来帮助我们将方法映射为store.commit调用

methods: {
  ...mapMutations({
    add: 'addTodos'
  }),
  handleClick() {
    let todo = { id: 4, text: 'writing', done: false };
    this.add(todo);
  }
}

Action: 操作状态(异步)

注意:actions通过提交mutations来操作状态,而不是直接变更。
actions 可以包含任意异步操作。

1. 声明

注册一个action:

const mutations = {
    addTodos: (state, todo) => {
        state.todos.push(todo);
    }
}
const actions = {
    addTodos: (context, todo) => {
        context.commit('addTodos', todo);
    }
}

通过参数结构可简化为:

const mutations = {
    addTodos: (state, todo) => {
        state.todos.push(todo);
    }
}
const actions = {
    addTodos: ({ commit }, todo) => {
        commit('addTodos', todo);
    }
}
2. 使用
methods: {
  handleClick() {
    let todo = { id: 5, text: 'driving', done: false };
    this.$store.dispatch('addTodos', todo);
  }
}
3. mapActions

同样,当有多个action的时候,我们可以通过mapActions辅助函数来帮助我们将方法映射为store.dispatch调用

methods: {
  ...mapActions({
    add: 'addTodos'
  }),
  handleClick() {
    let todo = { id: 5, text: 'driving', done: false };
    this.add(todo);
  }
}

对于复杂操作,action可以返回一个Promise对象,比如:

const actions = {
    addTodos: ({ commit }, todo) => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                commit('addTodos', todo);
                resolve();
            }, 1000)
        })
    }
}

这样就可以:

methods: {
    handleClick() {
      let todo = { id: 5, text: 'driving', done: false };
      this.$store.dispatch('addTodos', todo).then(() => {
        // ...
      })
    }
}

参考:https://vuex.vuejs.org/zh/

你可能感兴趣的:(Vue状态管理-Vuex)