参考博客:vuex单一状态树_Vuex 应用及原理_数据科学人工智能的博客-CSDN博客
组件内的状态管理流程
状态管理包含以下几部分:
- state,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,响应在 view 上的用户输入导致的状态变化
简易的状态管理方案
如果多个组件之间要共享状态(数据),使用上面的方式虽然可以实现,但是比较麻烦,而且多个组件之间互相传值很难跟踪数据的变化,如果出现问题很难定位问题。
当遇到多个组件需要共享状态的时候,典型的场景:购物车。我们如果使用上述的方案都不合适,我们会遇到以下的问题
- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。
对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
我们可以把多个组件的状态,或者整个程序的状态放到一个集中的位置存储,并且可以检测到数据的更改。你可能已经想到了 Vuex。
这里我们先以一种简单的方式来实现
什么是 Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具
devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
Vuex 是专门为 Vue.js 设计的状态管理库
它采用集中式的方式存储需要共享的数据
从使用角度,它就是一个 JavaScript 库
它的作用是进行状态管理,解决复杂组件通信,数据共享
什么情况下使用 Vuex
官方文档:
Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。引用 Redux 的作者 Dan Abramov 的话说就是:Flux 架构就像眼镜:您自会知道什么时候需要它。
store->index.js文件
import { createStore } from 'vuex'
import home from './modules/home'; //导入子仓库
export default createStore({
state: {
msg: '这是vuex的msg',
msg1: '这是官方推荐的vues的msg',
msg2: '这是使用辅助函数的方法',
books: ['book1', 'book2', 'book3', 'book4'],
obj: ['per1', 'per2', 'per3', 'per4', 'per5'],
num: 0,
num1: 100,
name: '主仓库的home'
},
getters: {
Get_Book_Num(state) {
return state.books.length;
},
GET_OBJ_NUM(state) {
return state.obj.length;
}
},
mutations: {
add(state) {
state.num += 2;
},
add1(state, n) {
state.num1 += n;
}
},
actions: {
async_add(context, n) {
setTimeout(() => {
context.commit('add1', n)
}, 2000)
},
getName() {
console.log('vuex')
},
getMsg() {
console.log('store的数据')
},
getMsg1() {
console.log('官方推荐的一种写法,vuex')
},
getMsg2() {
console.log('使用辅助函数,vuex')
}
},
modules: {
home
}
})
<script>
import { mapState, mapGetters, mapMutations } from "vuex";
import store from "../utils/store";
export default {
name: "Home",
components: {},
data() {
return {
// -----------------------------------------
// 一.直接解构
// state:store.state 两种方法解构
...store.state,
};
},
methods: {
...store.actions, //解构,直接找到数据
getName: store.actions.getName,
add() {
// console.log("a");
this.$store.commit("add");
},
...mapMutations(["add1"]),
// 传统用法
async_add(n) {
this.$store.dispatch("async_add", n);
},
},
// -----------------------------------------
// 二.计算属性
// 官方推荐的写法
computed: {
msg1() {
return this.$store.state.msg1;
},
books() {
return this.$store.state.books;
},
Get_Book_Num() {
return this.$store.getters.Get_Book_Num;
},
// -----------------------------------------------
// 三.辅助函数
// ...mapState("home", ["name"]), 子组件的name
// 假如两个同名的都想用
...mapState({
name: (state) => state.home.name,
app_name: (state) => state.name,
}),
// 使用辅助函数
...mapState(["msg2", "obj", "num", "num1"]),
...mapGetters(["GET_OBJ_NUM"]),
},
};
</script>
//子模块的
export default {
namespaced: true,
state() {
return {
name: '子仓库的home'
}
}
}
博客:vuex单一状态树_Vuex 应用及原理_数据科学人工智能的博客-CSDN博客
State
Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。
使用 mapState 简化 State 在视图中的使用,mapState 返回计算属性
mapState 有两种使用的方式:
接收数组参数
// 该方法是 vuex 提供的,所以使用前要先导入 import { mapState } from 'vuex' // mapState 返回名称为 count 和 msg 的计算属性 // 在模板中直接使用 count 和 msg computed: { ...mapState(['count', 'msg']), }
接收对象参数
如果当前视图中已经有了 count 和 msg,如果使用上述方式的话会有命名冲突,解决的方式:
// 该方法是 vuex 提供的,所以使用前要先导入 import { mapState } from 'vuex' // 通过传入对象,可以重命名返回的计算属性 // 在模板中直接使用 num 和 message computed: { ...mapState({ num: state => state.count, message: state => state.msg }) }