序言:在vue学习中,其实一直有一块功能不太明白,那就是vuex,我刚开始对它的理解是:可以储存数据,供全局使用。可是在之前没用vue的时候,如果想实现这种功能,我是使用localStorage。所以我得先弄明白,vuex和localStorage之间的区别。
一、vuex和localStorage的区别
好吧,虽然是讲解两者之间的区别,但我就还是先简单介绍下这两者到底是什么
1.vuex是什么
vuex官方解释
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
我们组件传值会用到:父子传值,兄弟组件传值...但要是对于多层嵌套的就比较麻烦了。这时可以使用vuex,把组件共享的状态提取出来,把共享的数据函数放在vuex,全局使用,任何组件都能共同它
2.localStorage是什么
localStorage作为HTML5 Web Storage的API之一,主要作用是本地存储。本地存储是指将数据按照键值对的方式保存在客户端计算机中,直到用户或者脚本主动清除数据,否则该数据会一直存在。也就是说,使用了本地存储的数据将被持久化。
ok,了解的它们的定义后,我们来讨论下,它们的区别
3.区别
1.vuex的数据是存储在内存中的,页面刷新就会丢失;localStorage是储存在计算机本地的,刷新不会消失
2.重点:vuex是用于组件之间传值(响应性的),localStorage是主要用在不同页面传值(其他页面更新数据了,当前页面得刷新才能更新对应数据,非响应式的)
这两点是最重要的区别,如果数据不变的话,localStorage是可以代替vuex,但是你想实现响应式的效果,一个组件中的数据改变,另一个组件也要响应改变,那么你就需要使用vuex。
状态管理设计的目的并不是用于做缓存,而是用来作为唯一数据源,同步状态,共享状态。
针对第一点,vuex刷新丢失的问题,常用的方式就是将vuex中的数据保存在localStorage里,两者结合
二、vuex的使用
注意点:
1.Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
2.你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
使用:
store文件夹下的index.js的文件中
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
oneComNumber: 10,
},
// Action支持异步调用Mutation来修改。 处理一些逻辑业务
actions: {
numberAddWait(context, v) { // 上下文和传过来的值
setTimeout(() => {
context.commit("numberAdd", v)
}, 1000);
},
},
// 用于操作一些数据 (state) 也可进行判断
mutations: {
numberAdd(state, v) {
// if (state.oneComNumber % 2) {
// console.log(4546546546);
// }
state.oneComNumber += v
},
numberMinus(state, v) { // 上下文和传过来的值
state.oneComNumber -= v
},
},
// 计算属性 辅助函数
getters: {
bigOneComNumber(state) {
return state.oneComNumber * 10
}
},
});
store实例中读取状态的最简单方法是在计算属性中返回:
computed: {
oneComNumber() {
return this.$store.state.oneComNumber;
},
},
但是当一个组件需要获取多个状态的时候,要是都这样声明就会显得重复和冗余。所以可以使用mapState辅助函数来帮助我们生成计算属性
import { mapState } from "vuex"; // 需要引入
export default {
name: "HelloWorld",
props: {
},
data() {
return {};
},
created() {
console.log(this.$store);
},
computed: {
// oneComNumber() {
// return this.$store.state.oneComNumber;
// },
// 这里是数组形式获取 用于方法名和属性名一样的时候
...mapState(["oneComNumber"]), // 展开运算符写入即可
// 这里是对象形式获取 用于方法名和属性名一样的时候
// ...mapState({'oneComNumber':'oneComNumber'}), // 展开运算符写入即可
},
};
Action
Action 类似于 mutation,不同在于:
1.Action 提交的是 mutation,而不是直接变更状态。
2.Action 可以包含任意异步操作。
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters 。
// Action支持异步调用Mutation来修改。 处理一些逻辑业务
actions: {
// 这里 就是等一段时间去执行
numberAddWait(context, v) { // 上下文和传过来的值
setTimeout(() => {
context.commit("numberAdd", v)
}, 1000);
},
},
在页面调用时可以直接调用:$store.dispatch('方法名称', 传递的参数)
<button @click="$store.dispatch('numberAddWait', n)">过一会再加</button>
使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用
import { mapActions } from "vuex";
export default {
methods: {
...mapActions(["numberAddWait"]),
},
};
调用
<button @click="numberAddWait(n)">过一会再加</button>
Mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。
// 用于操作一些数据 (state) 也可进行判断
mutations: {
numberAdd(state, v) {
state.oneComNumber += v
},
numberMinus(state, v) { // 上下文和传过来的值
state.oneComNumber -= v
},
},
直接调用 通过$store.commit('方法名',参数)调用
<button @click="$store.commit('numberAdd', n)">+</button>
<button @click="$store.commit('numberMinus', n)">-</button>
使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用
<button @click="numberAdd(n)">+</button>
<button @click="numberMinus(n)">-</button>
methods: {
// 与上面Actions mapActions用法一致 也有对象传值方法
...mapMutations(["numberAdd", "numberMinus"]),
},
可以看出这边和上面actions mapActions用法类似,但是直接调用的时候不一样,注意一下
actions直接调用是:$store.dispatch('方法名', 参数)
mutation直接调用是:$store.commit('方法名',参数)
Getter
有时候我们需要从 store 中的 state 中派生出一些状态,例如数据进行加工处理 例如放大倍数:这个时候可以在computed里面写计算属性,但是为了方便管理 Vuex提供了‘getter’
// 计算属性 辅助函数
getters: {
bigOneComNumber(state) {
return state.oneComNumber * 10
}
},
直接调用 进行显示
<h2>{{ $store.getters.bigOneComNumber }}</h2>
使用mapGetters 辅助函数
<h2>{{ bigOneComNumber }}</h2>
computed: {
...mapGetters(["bigOneComNumber"]),
},
Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。 主要用于多个文件/多个store,单个文件添加命名空间进行区别
namespaced: true,
在项目中,如果需要用到Vuex,可以将 store 分割成多个模块(module),每个模块拥有自己的 state、mutation、action、getter,这样你的模块具有更高的封装度和复用性,此时就用到了命名空间这个概念。( 默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的,这样使得多个模块能够对同一 mutation 或 action 作出响应。)
例如,新建文件oneCom.js
export default {
namespaced: true, // 空间命名
state: {
oneComNumber: 10,
peoppleList: [
{
id: 1,
name: "张三"
}
],
},
// Action支持异步调用Mutation来修改。 处理一些逻辑业务
actions: {
numberAddWait(context, v) { // 上下文和传过来的值
setTimeout(() => {
context.commit("numberAdd", v)
// context.state.oneComNumber += v
}, 1000);
},
},
// 用于操作一些数据 (state) 也可进行判断
mutations: {
numberAdd(state, v) {
// if (state.oneComNumber % 2) {
// console.log(4546546546);
// }
state.oneComNumber += v
},
numberMinus(state, v) { // 上下文和传过来的值
state.oneComNumber -= v
},
},
// 计算属性 辅助函数
getters: {
bigOneComNumber(state) {
return state.oneComNumber * 10
}
},
}
index.js
import Vue from "vue";
import Vuex from "vuex";
import oneCom from './oneCom'
Vue.use(Vuex);
export default new Vuex.Store({
strict: true,// 严格模式
// 多个模块进行管理 管理多个文件
modules: {
oneCom
}
});
页面.vue
<template>
<div class="home">
<button @click="numberAdd(n)">+</button>
<button @click="numberMinus(n)">-</button>
<button @click="numberAddWait(n)">过一会再加</button>
<select v-model="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<h2>{{ oneComNumber }}</h2>
</div>
</template>
<script>
import { mapMutations, mapActions, mapState } from "vuex";
export default {
name: "Home",
data() {
return {
n: 1,
};
},
created() {
},
methods: {
...mapMutations("oneCom", ["numberAdd", "numberMinus"]),
...mapActions("oneCom", ["numberAddWait"]),
},
computed: {
...mapState("oneCom", ["oneComNumber"]),
},
};
</script>