什么是vuex
Vuex 是一个专为 Vue 开发的应用程序的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
总之:Vuex 采用类似全局对象的形式来管理所有组件的公用数据,如果想修改这个全局对象的数据,得按照Vuex提供的方式来修改想·
使用vuex
要想使用vuex 我们需要
1. 安装Vuex
# npm 安装
npm install vuex
# yarn 安装
yarn add vuex
2. 引入vuex
在src目录下创建一个store目录,在该目录下创建index.js文件,用于创建Store对象
//用于创建Vuex的核心对象Store
//1.导入
import {createStore } from 'vuex'
//2.创建Store对象
const store = createStore({
//state 用于存储数据
state(){
return {
count:1,
}
},
//actions 用于响应组件中的事件
actions:{
},
//mutations 用于操作数据
mutations:{
}
});
//3.暴露出store对象
export default store;
第二步: 在main.js 使用store对象
import store from './store';
app.use(store);
``
第三步: 在 Vue 组件中, 可以通过 this.$store
访问store实例```
<template>
<h2>{{$store.state.count}}</h2>
</template>
<script>
export default {
name: 'App',
data() {
return {
};
},
components: {
},
methods: {
},
mounted() {
console.log(this.$store.state.count);
}
};
</script>
<style lang="css" scoped>
</style>
vuex的包含模块
- State:定义了应用状态的数据结构,可以在这里设置默认的初始状态。
- Getter:允许组件从 store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter
映射到局部计算属性。 - Mutation:是唯一更改 store 中状态的方法,而且要是同步函数。
- Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。
- Module:可以将 store 分割成模块(module)。每个模块拥有自己的
state、mutation、action、getter、甚至是嵌套子模块
vuex的工作流程就是:
(1)通过dispatch去提交一个actions,
(2) actions接收到这个事件之后,在actions中可以执行一些异步|同步操作,根据不同的情况去分发给不同的mutations,
(3)actions通过commit去触发mutations,
(4)mutations去更新state数据,state更新之后,就会通知vue进行渲染。
vuex的核心概念
1. State
假设我们有一个全局状态 count
的值为 5。那么,我们就可以将其定义为 state
对象中的 key
和 value
,作为全局状态供我们使用。如下:
import { createStore } from 'vuex'
export default createStore({
state: {
count:5 //总数:5
}
}
2. Getters
可以认为,getters
是store的计算属性,类似于computed,对state里的数据进行一些过滤,改造等等
getters 接受 state 作为其第一个参数
const getters ={
getNumDouble(state){
let sum=0;
sum=state.count*2;
return sum;
},
getTotalNum(state){
let totalNum=0;
state.phoneList.forEach(phoneList => {
totalNum+=phoneList.num;
});
return totalNum;
},
getTotalPrice(state){
let totalPrice=0;
state.phoneList.forEach(phoneList => {
totalPrice+=phoneList.num*phoneList.price;
});
return totalPrice;
}
}
3. Mutations
Vuex 给我们提供修改仓库 store 中的状态的唯一办法就是通过提交mutation
mutation必须是同步函数,这是 Vuex 设计时的一个核心原则:
Vuex 的状态跟踪机制依赖于同步的 mutations
当 mutation 异步执行时,Vuex 无法准确地知道何时状态已经更新,这可能导致无法正确地显示状态变化
在 mutations 中,可以直接修改state状态
//修改状态的方法
const mutations ={
addCount(state){
state.count++;
},
addCount2(state,payload) {
state.count+=payload.value;
},
defCount(state){
state.count=0;
},
addNum(state,payload) {
console.log(state.phoneList[0]);
console.log(payload.index);
state.phoneList[payload.index].num++;
},
delNum(state,payload){
state.phoneList[payload.index].num--;
},
delPhone(state,payload){
console.log(payload.index);
state.phoneList.splice(payload.index,1);
}
}
4. Action
Actions 是可以包含任意异步操作的函数
在 actions 中,不能直接修改状态(state),而需要通过 dispatch 方法提交一个 mutation 来更改状态
只有通过 action => mutations => states ,这个流程进行操作,具体步骤如下:
//actions 操作 定义事件,让组件触发事件
const actions = {
increment(context){
//调用moutations中的方法修改state
context.commit('addCount');
},
increment2(context,payload) {
setTimeout(
() => {
context.commit("addCount2",payload);
},3000
);
},
reduce(context){
context.commit('defCount');
},
addNum1(context,payload) {
context.commit('addNum',payload);
},
delNum1(context,payload) {
context.commit('delNum',payload);
},
delPhone1(context,payload) {
context.commit('delPhone',payload);
}
}
5. 操作数据
运用vuex语法糖 mapState、mapGetters 和 mapMutations
mapState:映射 state 到组件的计算属性:…mapState([“news”]) 就相当于 this.$store.state.news
mapGetters:映射 getters 到组件的计算属性:…mapGetters([“news”]) 就相当于 this.$store.getters.news
mapMutations :映射 mutations 到 组件的 methods:
…mapMutations([{ changeNews: “SET_NEWS” }]) 就相当于 给 SET_NEWS 重命名为 changeNews
this.changeNews(val) 就相当于 this.$store.commit(“SET_NEWS”, val)
<template>
<div>
<p>News: {{ news }}</p>
<button @click="submit">ChangeNews</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations } from "vuex";
export default {
computed: {
// 映射 state 到组件的计算属性
...mapState(["news"]) // 相当于 this.$store.state.news (vuex语法糖)
// 或者
// 映射 getters 到组件的计算属性
...mapGetters(["news"]) // 相当于 this.$store.getters.news (vuex语法糖)
},
methods: {
...mapMutations([{
// 将 changeNews 与 mutations中的 SET_NEWS 关联
changeNews: "SET_NEWS" // 相当于给 SET_NEWS 重命名为 changeNews
}]),
submit () {
let val = 'test news';
this.changeNews(val); // 相当于 this.$store.commit("SET_NEWS", val);
}
}
}
</script>
六、Vue3 setup 中使用
在 Vue2 项目中可以使用 this.$store 获取 vuex 里的数据和保存全局数据,但是在 Vue3 的 setup 函数里,并没有 this 这个概念,这里可以使用 useStore 代替,具体使用如下:
<template>
<div>
<p>News: {{ news }}</p>
<button @click="changeNews">Change News</button>
</div>
</template>
<script>
import { ref, onMounted } from 'vue';
import { useStore } from 'vuex';
export default {
setup() {
// 使用 useStore 钩子获取对 Vuex store 的引用
const store = useStore();
// 创建一个响应式引用来存储 news
const news = ref(store.state.news);
// 定义一个方法来改变 news
const changeNews = () => {
// 提交 mutation 来改变 news
store.commit('SET_NEWS', 'test news');
};
// 返回需要在模板中使用的响应式引用和方法
return {
news,
changeNews,
};
},
};
</script>
store/index.js:
// Vue3.x 中通过 createStore 创建 store
import { createStore } from 'vuex'
export default createStore({
state: {
news: null
},
mutations: {
SET_NEWS: (state, value) => {
state.news = value;
}
},
getters: {
news : state => { state.news || sessionStorage.news }
},
actions: {
getData(store) {
// 模拟异步
setTimeout(() => {
store.commit('SET_NEWS', '');
}, 2000);
}
},
modules: {}
})