Vuex

134 阅读3分钟

Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它提供了一种集中式存储管理应用的所有组件状态的方式,并以相应的规则保证状态只能按照预定的方式进行修改。Vuex 是 Vue.js 生态系统中的一部分,用于管理状态(State)。

五个核心

主要的核心概念包括:

  1. State(状态) : 包含应用级别的状态,是响应式的,即当状态发生变化时,所有使用该状态的地方都会自动更新。
  2. Getter(获取器) : 允许组件从状态中派生出一些值,类似于计算属性。
  3. Mutation(变更) : 是唯一允许修改状态的地方,它们是同步的。每个 mutation 都有一个字符串的事件类型(type)和一个回调函数,该回调函数就是实际进行状态修改的地方。
  4. Action(动作) : 类似于 mutation,不同在于 action 提交的是 mutation,而不是直接变更状态。可以包含异步操作。
  5. Module(模块) : 允许将 store 分割成模块,每个模块拥有自己的 state、getter、mutation、action。

使用 Vuex 的主要目的是解决 Vue.js 应用中组件之间共享状态的问题。在一个典型的 Vue.js 应用中,数据流是单向的,即从父组件传递到子组件。当应用的状态管理变得复杂时,组件之间的通信可能会变得困难,因为需要将状态通过多层组件传递。Vuex 提供了一种集中式管理状态的机制,允许组件直接从状态中读取数据,以及提交 mutation 来修改数据。这样,整个应用的状态就能够更加可控和可维护。

使用vuex

npm install vuex@next --sav

1-state

1- 把共享的状态放到state对象中

  • 创建一个仓库实例(store),把共享的状态放到state对象中
import { createStore } from 'vuex' 
const store = createStore({
    state () {
      return {
        isTabbarShow: true
      }
    }
})


export default store

//在main.js导入,并且使用
createApp(App)
.use(router)    
.use(store)  //使用仓库
.mount('#app')

2-直接使用

<template>
  <div id="app">
    {{ this.$store.state.name }}
    {{ this.$store.state.age }}
  </div>
</template>

3-mapState

通过 mapState把 store 映射到 组件的计算属性,就相当于组件内部有了 state 里的属性 知道这里为啥要用 ...展开吗使用对象展开运算符将此对象混入到外部对象中

computed: {
    ...mapState(['count', 'user'])
},

2-Mutation

1-修改状态

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。 当定义一个 mutation 时,你需要为其指定一个字符串的事件类型(type)以及一个回调函数(handler)。这个回调函数接受 state 作为第一个参数,其他参数(也就是 payload,如果有的话)作为后续参数

const store = createStore({
  state: {
    count: 0
  },
  mutations: {
    // 事件类型为 'increment'
    increment: function(state) {
      // 回调函数接受 state 作为第一个参数
      state.count++;
    },

    // 事件类型为 'incrementBy'
    incrementBy: function(state, amount) {
      // 回调函数接受 state 和额外的参数(payload)作为参数
      state.count += amount;
    }
  }
});

2-this.$store.commit() 触发

  • 在 methods 中定义一个方法,在这个方法里面进行触发 mutations 中的方法
// 在组件中提交 'increment' mutation
methods: {
  increment() { //不带参数
    this.$store.commit('increment');
  }
}

// 在组件中提交 'incrementBy' mutation,并传递额外的参数
methods: {
  incrementByAmount(amount) {//带参数
    this.$store.commit('incrementBy', amount);
  }
}

3-mapMutation


import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`

      // `mapMutations` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
    ])
  }
}

3-Getter

使用Getter 类似于计算属性,但是我们的数据来源是 Vuex 中的 state ,所以就使用 Vuex 中的 Getter 来完成,相当于对state

const store = createStore({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos (state) {
      return state.todos.filter(todo => todo.done)
    }
  }
})

1-this.$store.getter[名称]

<template> 
    <div id="app"> 
        {{ this.$store.getters.doneTodos }} 
    </div>
</template>

2-mapGetters

import { mapGetters } from 'vuex'

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

4-Action

Action 同样也是用来处理任务,不过它处理的是异步任务,异步任务必须要使用 Action,通过 Action 触发 Mutation 间接改变状态,不能直接使用 Mutation 直接对异步任务进行修改

1-this.$store.dispatch()

this.$store.dispatch('increment')

2-mapActions


import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

5-Modules

为了避免在一个复杂的项目 state 中的数据变得臃肿,Vuex 允许将 Store 分成不同的模块,每个模块都有属于自己的 stategetteractionmutation

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = createStore({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

1-命名空间

namespaced:true 如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

computed: {
  ...mapState({
    a: state => state.some.nested.module.a,
    b: state => state.some.nested.module.b
  }),
  ...mapGetters([
    'some/nested/module/someGetter', // -> this['some/nested/module/someGetter']
    'some/nested/module/someOtherGetter', // -> this['some/nested/module/someOtherGetter']
  ])
},
methods: {
  ...mapActions([
    'some/nested/module/foo', // -> this['some/nested/module/foo']()
    'some/nested/module/bar' // -> this['some/nested/module/bar']()
  ])
}