2

用最简的方式学Vuex

 1 year ago
source link: https://www.fly63.com/article/detial/11876
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

vuex是一个专为Vue.js应用程序开发的状态管理模式,采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,每一个Vuex应用的核心是store(仓库)。为了使用Vuex,首先需要安装该包,执行如下命令完成该安装过程。

npm install vuex@next --save

二、核心概念

Vuex中核心概念主要有五个:State、Getters、Mutations、Actions、Modules,每一部分都有自己的功用,下面先来看一段简单的代码,该代码中涉及到了这些核心概念,然后在该代码的基础上进一步理解。

// index.js文件
import {createStore} from "vuex";

import {moduleA} from "./module/moduleA";

export const store = createStore({
// Vuex允许将store分割成模块(module),每个模块拥有自己的state、mutation、action、getter、甚至是嵌套子模块
// 访问moduleA的状态:store.state.moduleA
modules: {
moduleA
}
});

// module/moduleA.js文件
// 对于模块内部的mutation和getter,接收的第一个参数是模块的局部状态对象
// 对于模块内部的action,局部状态通过context.state暴露出来,根节点状态则为context.rootState
// 对于模块内部的getter,根节点状态会作为第三个参数暴露出来

// 在带命名空间的模块内访问全局内容
// 如果希望使用全局state和getter,rootState和rootGetters会作为第三和第四个参数传入getter,也会通过context对象的属性传入action
// 若需要在全局命名空间内分发action或提交mutation,将{root: true}作为第三个参数传给dispatch或commit即可。

export const moduleA = {
// 默认情况下,模块内部的action、mutation和getter是注册在全局命名空间的,如果希望模块具有更高的封装度和复用性,可以通过添加namespaced:true的方式使其成为带命名空间的模块
namespaced: true,
state: {
testState1: 'xxxx',
testState2: {
a: 0,
b: 1
},
testState3: 0
},
// 有的时候需要从store中的state中派生出一些状态,此时可以将该部分抽象出一个函数供多处使用。
// Vuex允许在store中定义getter,像计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当他的依赖值发生了改变才会被重新计算
getters: {
// getter接收state作为其第一个参数
testGetter1: state => {
return state.testState1 + state.testState3;
},
// getter可以接受其他getter作为第二个参数
testGetter2: (state, getters) => {
return getters.testGetter1.length;
}
},
// 更改Vuex的store中的状态的唯一方法是提交mutation,每个mutation都有一个字符串的事件类型和一个回调函数,该回调函数接收state作为第一个参数,提交的载荷作为第二个参数
// 以相应的type调用store.commit方法来触发相应的回调函数
// Mutation必须是同步函数
mutations: {
testMutation1(state) {
// 变更状态
state.testState3++;
},
// 第二个参数是载荷
testMutation2(state, payload) {
state.testState1 += payload.content;
}
},
// Action提交的是mutation,而不是直接变更状态
// Action可以包含任意异步操作
// Action函数接受一个与store实例具有相同方法和属性的context对象,因此可以调用context.commit提交一个mutation,或者通过context.state和context.getters来获取state和getters。
// Action通过store.dispatch方法触发
actions: {
testAction1(context) {
setTimeout(() => {
context.commit('testMutation1');
}, 1000);
},
testAction2({commit}, payload) {
setTimeout(() => {
commit({
type: 'testMutation2',
content: payload.content
});
}, 1000);
}
}
};

State

Vuex使用单一状态树保存所有数据,作为唯一数据来源。如上所示代码,其包含了testState1、testState2、testState3,在组件中如何获取这些数据呢?(Vue3.x语法

<template>
<h1>组件三</h1>
<p>{{testState1}}</p>
<p>{{testState2}}</p>
<p>{{testState3}}</p>
</template>

<script setup>
import {computed} from 'vue';
import {useStore} from 'vuex';
// 通过useStore函数来访问store,与选项式api
const store = useStore();

// 从store中读取状态并显示到Vue组件中最简单的办法是将其绑定到计算属性上
// 如果想读取某一模块中的状态值,则需要store.state.模块名.状态名
const testState1 = computed(() => store.state.moduleA.testState1);
const testState2 = computed(() => store.state.moduleA.testState2.a + store.state.moduleA.testState2.b);
const testState3 = computed(() => store.state.moduleA.testState3);
</script>

<style lang="less"></style>

Getters

有的时候需要从store中的state中派生出一些状态,此时可以将该部分抽象出一个函数供多处使用。Vuex允许在store中定义getter,像计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当他的依赖值发生了改变才会被重新计算。

<template>
<h1>组件三</h1>
// ……
<p>{{testGetter1}}</p>
<p>{{testGetter2}}</p>
</template>

<script setup>
import {computed} from 'vue';
import {useStore} from 'vuex';
// 通过useStore函数来访问store,与选项式API
const store = useStore();

// ……

// 在computed函数中访问getter
// 如果访问非模块中的getter,直接store.getters.名称
// 如果访问模块中的getter,通过store.getters['getter路径']
const testGetter1 = computed(() => store.getters['moduleA/testGetter1']);
const testGetter2 = computed(() => store.getters['moduleA/testGetter2']);

</script>

<style lang="less"></style>

Mutations

更改Vuex的store中的状态的唯一方法是提交mutation,每个mutation都有一个字符串的事件类型和一个回调函数,该回调函数接收state作为第一个参数,提交的载荷作为第二个参数。(注意:Mutation必须是同步函数)

<template>
<h1>组件三</h1>
// ……
<button @click="handleMutationsClick">改变</button>
</template>

<script setup>
// ……

// 与mutations相应的type调用store.commit方法来触发相应的回调函数
const handleMutationsClick = () => {
store.commit('moduleA/testMutation1');
store.commit('moduleA/testMutation2', {
content: 'content'
});
};

</script>

<style lang="less"></style>

Actions

Actions类似于mutation,但是仍然有一些不同点,一方面其提交的是mutation,而不是直接变更状态;另一方面Action可以包含任意异步操作。

<template>
<h1>组件三</h1>
// ……
<button @click="handleActionsClick">改变Action</button>
</template>

<script setup>
// ……

// Action函数接受一个与store实例具有相同方法和属性的context对象,因此可以调用context.commit提交一个mutation,或者通过context.state和context.getters来获取state和getters。
// Action通过store.dispatch方法触发
const handleActionsClick = () => {
store.dispatch('moduleA/testAction1');
store.dispatch('moduleA/testAction2', {
content: 'test'
});
};
</script>

<style lang="less"></style>

Modules

由于使用单一状态树,应用的所有状态都会集中到一个较大的对象,当应用变的复杂时store会变的很难维护,为了解决该问题,Vuex允许将store分割成模块(module),每个模块拥有自己的state、mutation、action、getter、甚至是嵌套子模块,具体使用可见第二节中开头部分的代码,其中包含了其常见的使用方式。

3.1 插件基础

Vuex在实例化store的时候可以接受plugins选项,该选项可以添加一系列的插件,插件就可以帮助我们完成一系列的工作,节省人力和物力,下面我们自定义一个简单的插件并调用该插件。

// plugins/myPlugin.js
// 插件接收唯一的参数store
const myPlugin = store => {
// store上有一系列的方法,可以用在插件中https://next.vuex.vuejs.org/zh/api/#commit
// 注册一个动态模块用registerModule
// 替换store的根状态用replaceState
// 监听mutation的变化,该处理函数会在每个mutation完成后调用,接收mutation和经过mutation后的状态作为参数
store.subscribe((mutation, state) => {
console.log(mutation);
});
};

export default myPlugin;

// index.js
import {createStore} from "vuex";
import myPlugin from "./plugins/myPlugin";

export const store = createStore({
// ……
// 一个数组,包含应用在store上的插件方法,这些插件直接接收store作为唯一参数,可以监听mutation或者提交mutation
plugins: [myPlugin]
});

3.2 数据持久化插件

Vuex的状态存储并不能持久化,只要一刷新页面数据就丢失了,此时可引入vuex-persist插件来解决该问题,其会将状态保存至cookie或者localStorage中。

import {createStore} from "vuex";
import VuexPersistence from "vuex-persist";
import myPlugin from "./plugins/myPlugin";

// 利用该插件可实现对store数据的持久化
const vuexLocal = new VuexPersistence({
storage: window.localStorage
});

export const store = createStore({
// ……
// 一个数组,包含应用在store上的插件方法,这些插件直接接收store作为唯一参数,可以监听mutation或者提交mutation
plugins: [myPlugin, vuexLocal.plugin]
});
原文:https://mp.weixin.qq.com/s/cGsqcO8HDxvZIX9xnYJj2g

链接: https://www.fly63.com/article/detial/11876


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK