前言
在之前的文章中,我们已经对 Vue.js 有了一定的了解。今天我们要对Vue官方的状态共享管理器Vuex进行详细讲解,将其基本吃透,目标是面对大多数业务需求;
一、介绍
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 随着 Vue 一同开发,并且是 Vue.js 官方维护的状态管理库。
在 Vue.js 应用程序中,组件之间的通信是通过 props 和事件来实现的,这种方式在组件层级较浅()的情况下可以很好地管理状态,但是随着应用规模的增长,状态的管理会变得复杂和困难。这时候就需要使用 Vuex 来解决状态管理的问题。
Vuex 中包含以下核心概念:
State
(状态): 即存储在 Vuex 中的数据,它代表了整个应用的状态。Getter
(获取器): 用于从状态树state中派生出一些状态,类似于计算属性Mutation
(变更): 是唯一允许修改 Vuex 中状态的地方,但是必须是同步函数。Action
(动作): 用于提交 mutation,而不是直接变更状态。可以包含任意异步操作。
二、Vuex的适用范围
Vuex
适用于中大型的 Vue.js 应用程序,特别是当应用的状态变得复杂且需要在多个组件之间共享时。它提供了一种集中式管理状态的方式,使得状态管理变得更加可预测和可维护。
Vuex既适用于Vue2,也适用于Vue3;
当应用中包含以下情况时,考虑使用 Vuex:
- 多个组件需要共享同一状态。
- 多个视图依赖于同一状态。
- 有大量的组件需要访问和修改状态。
当应用程序的状态变得较简单或者组件之间的状态传递并不频繁时,可能并不需要使用 Vuex。在这种情况下,可以考虑使用 Vue.js 的局部状态(data)来管理组件的状态。
三、Vuex的主要组成部分
Vuex 的核心包含四个主要部分:State
、Getters
、Mutations
和 Actions
。
1.State
State 是 Vuex 存储数据的地方,它类似于组件中的 data。State 中的数据可以通过 this.$store.state 访问。
①在根Vuex中定义state
state: {message: 'Hello, Vuex!', // 字符串类型变量count: 0, // 数字类型变量isActive: false, // 布尔类型变量user: { // 对象类型变量name: 'John Doe',age: 30},items: ['apple', 'banana', 'orange'], // 数组类型变量currentDate: new Date() // 引用类型变量}
②在 Vuex 中定义模块的 state:
// Module A
const moduleA = {state: {message: 'Hello from Module A',count: 0}
};// Module B
const moduleB = {state: {message: 'Hello from Module B',isActive: true}
};// Vuex Store
const store = new Vuex.Store({modules: {moduleA,moduleB}
});
在这个示例中,我们定义了两个模块 moduleA
和 moduleB
,每个模块都有自己的 state
对象,包含了不同的状态属性。
以下是两种在组件中使用 Vuex state 的案例:
①根Vuex直接访问 $store.state:
<template><div><p>Message: {{ $store.state.message }}</p><p>Count: {{ $store.state.count }}</p><p>Active: {{ $store.state.isActive }}</p><p>User: {{ $store.state.user.name }} ({{ $store.state.user.age }})</p><p>Items: {{ $store.state.items }}</p><p>Current Date: {{ $store.state.currentDate }}</p></div>
</template>
特点:
- 直接访问
$store.state
可以在模板中直接使用 Vuex store 中的 state,语法简单直接。 - 在模板中使用
$store.state
可能会导致代码冗长,难以维护,尤其是在大型应用中。
② 根Vuex使用 mapState 辅助函数:
<template><div><p>Message: {{ message }}</p><p>Count: {{ count }}</p><p>Active: {{ isActive }}</p><p>User: {{ user.name }} ({{ user.age }})</p><p>Items: {{ items }}</p><p>Current Date: {{ currentDate }}</p></div>
</template><script>
import { mapState } from 'vuex';export default {computed: {...mapState(['message','count','isActive','user','items','currentDate']) // 传入数组}
};
</script>
特点:
- 使用 mapState 可以将 Vuex store 中的 state 映射到组件的计算属性中,使得在模板中可以直接使用这些计算属性,映射在计算属性中才能保证实时响应。
- 使用 mapState 可以简化模板中对 Vuex state 的访问,提高代码的可读性和可维护性。
- mapState 需要传入一个数组或对象作为参数,这个参数包含了需要映射的 state 属性,这样可以灵活地选择需要的属性映射到组件中。
③直接访问模块 $store.state
<template><div><p>Message from Module A: {{ $store.state.moduleA.message }}</p><p>Count from Module A: {{ $store.state.moduleA.count }}</p><p>Message from Module B: {{ $store.state.moduleB.message }}</p><p>isActive from Module B: {{ $store.state.moduleB.isActive }}</p></div>
</template>
④模块state
使用 mapState
辅助函数
<template><div><p>Message from Module A: {{ moduleA_message }}</p><p>Count from Module A: {{ moduleA_count }}</p><p>Message from Module B: {{ moduleB_message }}</p><p>isActive from Module B: {{ moduleB_isActive }}</p></div>
</template><script>
import { mapState } from 'vuex';export default {computed: {...mapState('moduleA', [ // 模块名'message as moduleA_message', // 使用别名来避免与全局变量冲突'count as moduleA_count' // count是原名,moduleA_count是别名]),...mapState('moduleB', ['message as moduleB_message','isActive as moduleB_isActive'])}
};
</script>
⑤用mapState函数的对象形式映射模块状态
在模板中,你可以直接使用这两个计算属性来获取模块 A 和模块 B 中的 message 状态。下面是模板中如何使用这两个计算属性的示例:
<template><div><p>Message from Module A: {{ moduleA_message }}</p><p>Message from Module B: {{ moduleB_message }}</p></div>
</template><script>
import { mapState } from 'vuex';export default {computed: {...mapState({// 使用命名空间来映射模块中的状态moduleA_message: state => state.moduleA.message, // 模块A下的message对象,别名为moduleA_messagemoduleB_message: state => state.moduleB.message // moduleA_message可以用引号括住,也可以不要引号})}
};
</script>
在这个案例中,我们展示了五种使用 的 state
的方式。基于模块创建的state使用和基于根Vuex的state使用;
2.Getter
①定义
Getter
允许我们在Vuex
中派生状态,它类似于组件中的 computed
属性。Getter
可以接收 state
作为参数,然后返回派生出的状态。
const store = new Vuex.Store({state: {todos: [{ id: 1, text: 'Todo 1', done: true },{ id: 2, text: 'Todo 2', done: false }]},getters: {doneTodos: state => {return state.todos.filter(todo => todo.done);}}
});
在 Vuex 中,Getter 可以用来对 store 中的 state 进行一些计算或筛选,从而得到我们想要的状态,而不需要直接修改原始的 state。这样做有几个好处:
- 组件中的状态派生: Getter 可以用来将 store 中的状态进行处理,然后在组件中直接使用这些派生出的状态,而无需在组件中进行复杂的计算逻辑。
- 避免直接修改 state: 使用 Getter 可以避免直接修改 store 中的 state,使得代码更加可维护和可测试,同时也保证了 Vuex 的单向数据流。
- 重用性和可组合性: 可以将 Getter 进行组合和重用,使得代码更加灵活和可扩展。
②组合性和复用性
在上面的示例中,我们定义了一个名为 doneTodos
的 Getter
,它接收 store
中的 state
作为参数,然后返回一个数组,这个数组包含了所有已完成的 todo
。在组件中可以直接使用 doneTodos
这个 Getter
来获取已完成的 todo
,而无需在组件中手动筛选 todo
数组。这样可以使得组件中的代码更加简洁和清晰。
对于第三点的复用性和组合性,案例如下:
const store = new Vuex.Store({state: {todos: [{ id: 1, text: 'Todo 1', done: true },{ id: 2, text: 'Todo 2', done: false }]},getters: {doneTodos: state => {return state.todos.filter(todo => todo.done);},undoneTodos: state => {return state.todos.filter(todo => !todo.done);},totalTodosCount: state => {return state.todos.length;},undoneTodosCount: (state, getters) => {return getters.doneTodos.length; // undoneTodosCount Getter 使用了 doneTodos Getter 来获取所有已完成的任务}}
});
③模块间的 Getter 访问
在 Vuex 中,一个模块的 Getter 可以访问其他模块的 state 和 Getter,以及根模块的 state 和 Getter。这是因为在 Getter 中,可以通过参数访问当前模块的 state 和 Getter,以及 rootState 和 rootGetters。同理Vuex根getters也可以访问其他模块的state和getters;案例代码如下:
const store = new Vuex.Store({modules: {moduleA: {state: {message: 'Module A Message'},getters: {moduleA_message: state => state.message}},moduleB: {state: {message: 'Module B Message'},getters: {moduleB_message: state => state.message}},moduleC: {getters: {combinedMessages: (state, getters, rootState, rootGetters) => {const moduleA_message = rootGetters['moduleA/moduleA_message'];const moduleB_message = rootGetters['moduleB/moduleB_message'];return `${moduleA_message} - ${moduleB_message}`;}}}}
});
const store = new Vuex.Store({modules: {moduleA: {state: {message: 'Module A Message'},getters: {moduleA_message: state => state.message}}},getters: {moduleA_message: (state, rootGetters) => {return rootGetters['moduleA/moduleA_message'];}}
});
从这个角度看,rootGetters
是一个对象,其中每个键代表每个模块名称,值为每个模块对于的getter
;
同理rootState.moduleName.stateName
可以访问不同模块间的state
属性;
④缓存特性
Getter
在默认情况下是具有缓存特性的,意味着在相同的状态下多次调用相同的 Getter,只会计算一次,并且在下次调用时直接返回缓存的结果,而不会重新计算。这可以提高性能,避免重复计算。
在 Vuex
中,Getter
是一个函数,可以接收 state
、getters
和 rootState
作为参数。这使得 Getter 具有更大的灵活性, 由于 Getter 是函数,因此可以在其中进行条件判断和计算,根据不同的情况返回不同的值,从而实现更灵活的状态派生和计算逻辑;
3. Mutations
①定义
Mutations 是 Vuex 中用来唯一能修改状态的函数,类似于组件中的 methods。Mutation 函数接收当前状态 (state) 作为第一个参数,并且可以接收额外的参数作为需要修改的数据。Mutation 必须是同步函数,不能包含异步操作。
const store = new Vuex.Store({state: {count: 0},mutations: {increment(state) {state.count++;},decrement(state) {state.count--;},incrementBy(state, payload) {state.count += payload.amount;}}
});
- Mutations 是同步的:Mutations 中的操作是同步执行的,不支持异步操作。
- 只能通过 Mutations 修改状态:在 Vuex 中,强制规定只能通过 Mutations 来修改状态,这样可以更好地追踪状态的变化,并且使得状态变更更加可控。
②在组件中使用
methods: {increment() {this.$store.commit('increment');},decrement() {this.$store.commit('decrement');},incrementBy(amount) {this.$store.commit('incrementBy', { amount }); // this指的是Vue实例,第二个参数等于{ amount: amount }}
}
③应用场景
- 修改单个状态:当需要修改 Vuex 中的某个单个状态时,可以使用 Mutation。
- 批量修改状态:可以一次性修改多个状态,保持状态变更的原子性。
- 追踪状态变化:通过 Mutation,可以清晰地追踪状态的变化,便于调试和排查问题。
下面是应用场景2的一个案例:
const store = new Vuex.Store({state: {count: 0,message: 'Hello, Vuex!'},mutations: {updateState(state, payload) {// payload 是一个包含多个状态的对象Object.assign(state, payload);}},actions: {updateState(context, payload) {context.commit('updateState', payload);}}
});// 在组件中调用这个 Mutation 来批量修改状态
this.$store.commit('updateState', { // 如果是模块,则this.$store.commit('moduleName/mutationName', payload)count: 10,message: 'Hello, Vuex! Updated!'
});
Object.assign(state, payload);是浅拷贝方法,因此组件中这样使用,可能会导致整个模块或者全局都改变!
4. Actions
①定义
Action
类似于 Mutation
,但具有异步操作的能力;它提交的是 Mutation,而不是直接变更状态。其通过 store.dispatch
触发Mutations 来变更状态。
Actions 接收一个上下文对象 (context)
,这个context
是包含了与 Vuex
实例具有相同方法和属性的对象,例如 state
、commit
、dispatch
等;
const store = new Vuex.Store({state: {count: 0},mutations: {increment(state) {state.count++;}},actions: {incrementAsync(context) {setTimeout(() => {context.commit('increment'); // 变量名为对应mutation名称}, 1000);}}
});
在 Vuex 中,每个模块module内部都有一个上下文对象 (context),它提供了与 根store 实例具有相同方法和属性的对象,包括 state(属性)、commit(方法,提交mutation)、dispatch(方法,分发action触发异步) 等。这样设计的目的是为了让模块内部的 actions、mutations、getters 等能够访问和操作模块的局部状态,而不需要通过全局的 store 对象。
②组件中使用
Actions
可以通过 store.dispatch
方法在组件中触发。在 Action
中,可以执行异步操作,例如发起 HTTP 请求、定时器等,然后在异步操作完成后提交 Mutations 来变更状态
// 组件中触发 Action
methods: {incrementAsync() {this.$store.dispatch('incrementAsync');}
}
③特点
- 异步操作:Actions 可以执行任意异步操作,例如 HTTP 请求、定时器等。
- 提交 Mutations:Actions 通过 context.commit 来提交 Mutations,从而变更状态。
- 触发方式:Actions 可以通过 store.dispatch 方法在组件中触发。
④应用场景
- 处理异步逻辑:例如发起 HTTP 请求获取数据后提交 Mutations 更新状态。
- 封装复杂逻辑:将复杂的业务逻辑封装在 Action 中,使组件更加简洁。
- 异步操作:Actions 可以执行异步操作,但应该避免在 Action 中进行直接的状态变更。
- 触发方式:Actions 必须通过 store.dispatch 方法来触发。保证顺序执行和稳定;
⑤WebGIS中的应用场景
- 异步数据获取: 在 WebGIS 应用中,通常需要从服务器获取地理空间数据、地图瓦片、地图图层配置等信息。Actions 可以用于发起异步请求,并在数据获取完成后更新 Vuex 中的状态,以便在地图中显示数据。
- 用户交互和事件处理: 用户在地图上的操作通常会触发一系列的事件,例如点击地图、拖动地图、放大缩小地图等。Actions 可以用于监听这些事件,并根据用户的操作进行相应的状态更新或地图操作。
- 状态管理: WebGIS 应用中通常包含复杂的地图状态,例如地图的视图范围、图层的可见性、图层样式等。Actions 可以用于管理这些状态,并在需要时进行状态的更新和同步。
- 地图操作和交互效果: Actions 可以用于执行地图操作,例如平移地图、缩放地图、绘制图形等,并根据操作结果更新地图的状态和展示效果。
- 应用配置和设置: Actions 可以用于处理应用的配置信息和用户设置,例如地图的初始配置、图层的加载顺序、应用的主题设置等。
四、Vuex的常用函数
1.mapState:
mapState 函数用于将 Vuex 中的 state 映射为组件的计算属性。它接收一个数组或对象作为参数,数组中可以是 state 中的属性名,也可以是对象形式,对象的键是组件中的属性名,值是 state 中的属性名或者是一个返回状态的函数。这样,在组件中就可以直接使用这些计算属性,无需再通过 $store.state.xxx 的方式访问 Vuex 中的状态。
import { mapState } from 'vuex';export default {computed: {// 使用数组...mapState(['count', 'message']),// 使用对象...mapState({user: state => state.userInfo,isLoggedIn: state => state.auth.isLoggedIn})}
};
2.mapGetters:
mapGetters
函数用于将 Vuex
中的 getters
映射为组件的计算属性。它接收一个数组或对象作为参数,用法与 mapState
相似,可以使用数组形式或者对象形式来进行映射。
import { mapGetters } from 'vuex';export default {computed: {...mapGetters(['doneTodosCount', 'undoneTodosCount']),...mapGetters({formattedMessage: 'formattedMessage'})}
};
3.mapMutations:
mapMutations
函数用于将 Vuex
中的 mutations
映射为组件的方法。它接收一个数组或对象作为参数,数组中是 mutations
中的方法名,对象形式的键是组件中的方法名,值是 mutations 中的方法名。
import { mapMutations } from 'vuex';export default {methods: {...mapMutations(['increment', 'decrement']),...mapMutations({setUserName: 'SET_USER_NAME'})}
};
数组方法直接用,对象方法可以改别名后使用
...mapMutations(['increment', 'decrement'])
等价于以下代码:
{increment: function() {return this.$store.commit('increment');},decrement: function() {return this.$store.commit('decrement');}
}
它将 mapMutations
返回的对象展开,将其中的每个方法映射到组件中,使得用户可以直接调用 this.increment()
和 this.decrement()
来提交对应的 mutations
。
4.mapActions:
mapActions
函数用于将 Vuex
中的 actions
映射为组件的方法。用法与 mapMutations
类似,接收一个数组或对象作为参数,数组中是 actions 中的方法名,对象形式的键是组件中的方法名,值是 actions 中的方法名。
import { mapActions } from 'vuex';export default {methods: {...mapActions(['login', 'logout']),...mapActions({fetchUserData: 'FETCH_USER_DATA'})}
};
通常情况下,mutation
用于同步地修改状态,而 actions
则用于包含异步操作的场景。在 actions
中可以调用多个 mutation
来修改状态,但通常不会在 actions 中定义不需要通过 mutation 修改状态的独立方法。这样可以保持状态变更的可追踪性和可维护性。
当在 actions 中执行异步操作时,可能需要在异步操作完成后修改多个状态。例如,假设有一个购物车功能,需要在用户点击结账按钮时执行以下操作:
- 清空购物车中的商品列表。
- 将商品列表中的商品添加到订单列表中。
- 将订单总金额清零。
在这种情况下,可以在 actions
中调用多个 mutation
来修改这些状态。以下是示例代码:
const store = new Vuex.Store({state: {cart: [{ id: 1, name: 'Product 1', price: 10 },{ id: 2, name: 'Product 2', price: 20 },// 其他商品],orders: [],},getters: {totalAmount: state => {return state.cart.reduce((total, product) => total + product.price, 0); // 累加,p1为累加器,p2为当前元素,0为初始值}},mutations: {clearCart(state) {state.cart = [];},addToOrders(state, products) {state.orders.push(...products);},resetTotalAmount(state) {state.totalAmount = 0;}},actions: {checkout({ commit, state }) {// 模拟异步操作,例如向后端发送订单请求setTimeout(() => {// 异步操作完成后,调用多个 mutation 来修改状态commit('addToOrders', state.cart); // 添加到订单commit('clearCart'); // 清空购物车commit('resetTotalAmount'); //清空总额}, 1000);}}
});
在上面的示例中,checkout action 执行了一系列异步操作,然后调用了多个 mutation 来修改状态。
五、Vuex的应用场景
1.管理购物车状态:
- 应用场景:在线商城中,用户可以将商品加入购物车,修改商品数量或移除商品。
- 实现方式:使用 Vuex 来管理购物车的状态,包括购物车中的商品列表、商品数量、总价等信息。通过 mutations 修改购物车状态,例如增加商品、删除商品、修改商品数量等操作。
2.用户认证状态管理:
- 应用场景:网站或应用中需要对用户进行认证,登录后可以访问特定的页面或功能,未登录状态下需要跳转到登录页面。
- 实现方式:使用 Vuex 存储用户的认证状态,例如用户信息、登录状态、权限等信息。通过 mutations 修改用户认证状态,例如登录、注销、更新用户信息等操作。在需要认证的页面或功能中,通过 getters 获取用户的认证状态来控制页面展示逻辑。
3.表单数据管理:
- 应用场景:页面中存在复杂的表单,包含多个输入框、复选框、下拉框等元素,需要实时根据用户输入更新表单数据。
- 实现方式:使用 Vuex 存储表单的状态,例如表单数据、验证状态、提交状态等信息。通过 mutations 修改表单数据状态,例如更新输入框值、切换复选框状态等操作。通过 getters 获取表单数据状态,实时展示给用户,同时通过 actions 处理表单提交逻辑,例如表单验证、数据提交等操作。
4.页面之间共享的数据状态:
- 应用场景:不同页面或组件之间需要共享相同的数据状态,例如全局的主题设置、语言设置等。
- 实现方式:使用 Vuex 存储全局的数据状态,例如主题颜色、语言设置等信息。通过 mutations 修改全局数据状态,例如切换主题、切换语言等操作。通过 getters 获取全局数据状态,实时应用到页面或组件中。
5.WebGIS中的应用场景
在 WebGIS 中,Vuex 可以应用于许多场景,以管理地图状态、图层数据、用户交互等。以下是一些常见的 WebGIS 应用场景:
1.地图状态管理:
- 应用场景:在 WebGIS 应用中,用户可能会对地图进行缩放、平移、旋转等操作,这些操作会导致地图状态的变化,如当前的中心点、缩放级别、旋转角度等。
- 实现方式:使用 Vuex 存储地图的状态信息,例如中心点坐标、缩放级别、旋转角度等。通过 mutations 修改地图状态,例如更新中心点坐标、修改缩放级别等操作。通过 getters 获取地图状态信息,以便在地图组件中实时展示。
2.图层数据管理:
- 应用场景:WebGIS 应用中通常包含多个图层,如矢量图层、栅格图层、图像图层等,这些图层可能需要根据用户的操作进行显示、隐藏、更新等操作。
- 实现方式:使用 Vuex 存储图层的状态信息,例如图层的可见性、透明度、样式等。通过 mutations 修改图层状态,例如显示/隐藏图层、更新图层样式等操作。通过 getters 获取图层状态信息,以便在地图组件中实时控制图层的显示。
3.用户交互管理:
- 应用场景:WebGIS 应用中用户可能会进行交互操作,如点击地图、绘制要素、查询信息等,这些操作需要及时响应并更新相关状态。
- 实现方式:使用 Vuex 存储用户交互的状态信息,例如点击的位置、绘制的要素、查询到的信息等。通过 mutations 修改用户交互状态,例如记录点击位置、绘制要素、查询结果等操作。通过 getters 获取用户交互状态信息,以便在地图组件中实时展示用户的操作。
六、Vuex的最佳实践思路
针对一个中大型WebGIS项目,可以采用以下方法论来设计和组织 Vuex 的解决方案:
- 模块化设计:
○ 将 Vuex store 拆分成多个模块,每个模块专注于处理特定的业务逻辑或状态管理。
○ 根据业务领域的不同,可以将模块划分为地图模块、用户模块、数据模块等,每个模块管理对应领域的状态和逻辑。 - 命名空间:
○ 在定义 Vuex 模块时,可以使用命名空间来避免不同模块之间的命名冲突,确保模块的状态和操作的唯一性和可识别性。
○ 通过在模块定义时设置 namespaced: true 来启用命名空间。 - 拆分状态:
○ 将 Vuex store 中的状态拆分成不同的模块级别的状态,每个模块负责管理自己的状态。
○ 例如,地图模块可以管理地图状态(中心点坐标、缩放级别等)、图层状态等,用户模块可以管理用户信息、权限状态等。 - 常量管理:
○ 使用常量来表示 mutation 和 action 的名称,以提高代码的可读性和维护性。
○ 将常量集中管理,可以在单独的文件中定义常量,并在需要使用的地方引入,避免重复定义和错误拼写。 - 异步操作:
○ 对于需要进行异步操作的情况,例如 API 请求、数据加载等,使用异步 action 来处理。
○ 在异步 action 中进行异步操作,并在操作完成后提交 mutation 来更新状态,保持 Vuex 单向数据流的规范。 - 模块间通信:
○ 对于模块之间需要进行通信的情况,可以通过根模块来协调不同模块之间的状态和操作。
○ 使用根模块的 state 和 getters 来访问和管理不同模块的状态,使用根模块的 mutations 和 actions 来触发和处理模块间的操作。 - 代码组织:
○ 合理组织 Vuex 相关的代码结构,例如将常量、mutations、actions、getters 等分别放置在不同的文件中,便于管理和维护。
○ 可以按照功能模块或业务领域来组织代码结构,使代码清晰易读。
七、总结
在本文中,我们全面地探讨了 Vuex
,这是一个专为 Vue.js 应用程序开发的状态管理模式。通过学习 Vuex 的基础概念、高级用法、辅助函数和应用场景,我们深入理解了 Vuex 的工作原理和应用方法。
通Vuex 提供了一种统一的状态管理方案,使得不同组件之间可以轻松共享状态,并且保证状态的一致性。
在实际项目中,我们可以利用 Vuex 来管理购物车状态、用户认证状态、表单数据状态等。通过合理地设计和使用 Vuex,我们可以有效地管理复杂的状态逻辑,并且提高项目的开发效率和质量。
文章参考
-
开始 | Vuex:
-
vuex的超详细讲解和具体使用细节记录(篇幅略长,建议收藏) - 知乎
-
Vuex的全面简约版总结_vuex参考文献-CSDN博客
项目地址
- Github地址
- 拓展阅读
如果觉得我的文章对您有帮助,三连+关注便是对我创作的最大鼓励!或者一个star🌟也可以😂.