前端小菜鸡浅学vuex

118 阅读3分钟

Vuex

主要就是一个状态管理的工具,其核心就是一个store(仓库)这个仓库中有很多的状态(state)

Vuex的相比较于全局对象的特点:

  1. Vuex的状态存储是响应式的。当vue组件访问store读取状态时,如果store的状态发生变化,相应的组件也会相应的发生变化
  2. 不可以直接修改store中的状态。如果要改,需通过提交(commit)mutation。这样就可以跟踪每一个状态的变化

创建一个store

import {createApp} from 'vue'
import {createStore} from 'vuex'//创建store实例
const store = createStore({
    state(){
        return {
            count:0
        }
    },
    mutations:{
        increment(state){
            state.count++
        }
    }
})
const app = createApp({/*根组件*/})
app.use(store)
​

通过store.commit来触发mutation状态更新, 在vue组件中可以通过this.$store.commit触发

store.commit('increment')
//vue组件
methods:{
    increment(){
        this.$store.commit(increment)
    }
}

注意:这是通过commit触发mutation来修改状态的

State

  1. vuex使用单一状态树,一个对象就可以包含所有的状态。

  2. 如何在vue组件中获取vuex状态

    由于vuex的状态是响应式的,所以简单的方法就是通过计算属性进行获取并返回

    const Counter = {
      template: `<div>{{ count }}</div>`,
      computed: {
        count () {
          return this.$store.state.count
        }
      }
    }
    当组件中store.state.count发生变化时候,都会重新求取计算属性,并且触发更新相关的DOM
    

    在vuex官网中也有一种方法能够帮助我们生成计算属性那就是mapState

Getter

那如何获取到状态呢?Getter就来了

在vuex中允许我们在store中定义getter(在这里我们可以认为是store的计算属性)

Getter有三种访问状态的方式:

  1. 通过属性访问
  2. 通过方法访问
  3. mapGetters辅助函数访问

具体的例子大家可以参考这里

Mutation

注意我认为重点的来了

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个 回调函数 (handler)

提交载荷(Payload)

可以向store.commit传入第二个参数,也就是mutation的载荷(大多数情况下,载荷应该是一个对象)

重点:Mutation必须是同步函数

在组件中提交Mutation

其实还是上面说的,要通过store.commit来提交Mutation,或者使用mapMutation 辅助函数将组件中的 methods 映射为 store.commit 调用

Action

Action 类似于 mutation,不同在于:

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

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

分发Action

通过store.dispatch()方法进行分发,有人会想,直接分发mutation不好吗?记得上面的重点吗?

因为 mutation必须是一个同步函数,但是 Action 就不受约束!我们可以在 action 内部执行异步操作

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}
​