Vuex是应用程序的状态(state)管理器 。它采用集中式存储、管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
把vue应用的数据放在一个地方管理。 每一个vue的组件都可以有data项(有自己的数据),我们可以通过父子之间的相互传递,进行数据的交换。
父传子:自定义的属性; 子组件用props
子传父:自定义的事件;子组件用emit
1.为什么要用Vuex呢?
答:如果你的项目中,需要用到在各个子组件中共享数据,则你就需要用到vuex。 因为子组件与另一个组件之间共享(它们是兄弟,表兄弟,堂兄弟关系)数据,非常麻烦。
2.使用步骤:
-
先引入vue.js,再引入vuex.js,此时,你已经可以在控制台中访问vuex。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3OS0wetN-1653739481823)(C:\Users\67333\AppData\Roaming\Typora\typora-user-images\1653737780906.png)]
-
实例化vuex中的store对象
实例化一个对象,就是通过new的方式去创建一个对象
-
将实例化对象store注入到Vue实例中
-
定义子组件并在根组件注册子组件
-
使用store中的数据
一旦你在vue的实例中注入了store,则在所有的子组件及 vue的实例中,你都可以通过:this.$store.state.数据名 去获取数据 。
可以通过this.$store.state.数据名 = 值 去暴力修改数据,但是,vuex反对这么做。
3. Vuex最核心的概念-store
Vuex 应用的核心就是 store(仓库)。 store是一个容器,包含着vue应用的状态(state)。
两大特点 :
- Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
- 可以方便地跟踪每一个状态的变化。我么不能直接更改 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交(commit) mutations(后面会说明mutations是什么)。
4. Vuex的四个概念
- state:存放数据。在组件之间共享。
- mutations:修改数据的唯一途径。
- getters:从state中的数据中,取出一部分来,依据数据项产生新的结果。类似于vue实例中的computed(计算属性)。
- actions:在对数据实现异步操作时,要用的。
1. state
仓库中的数据就存放在state中,state中的数据在组件之间共享。
1. 那么在组件中应该如何去获取保存在vuex.中的数据?
方法一:$store.state.数据名
2. 方法二:变通一下,手动映射,在组件内部用一个计算属性来获取数据。
注意:不要设置成组件的data。
为什么可以设置为计算属性,而不要设置成data?
原因是:计算属性一般就是只读的:通过它去获取数据。而data是可以直接修改的,如果你绑定到data中的数据项是引用数据类型,则对data的修改也会影响到vuex中的数据:
3. 方法三:mapState
this.$store.state.amount写起来比较麻烦。在vuex中提供一个便捷的写法:mapState。它的作用:是把写在vuex.store.state中的数据直接映射到组件中计算属性中。
(1)在组件的script中,先导入一个特殊的函数mapState.
(2)直接在组件的计算属性中,把仓库中的状态自动映射成本组件内的计算属性。
mapState([“count”,”num1”,”num2”]):mapState是一个函数,这里就是调用这个函数,实参是一个数组[“count”,”num1”,”num2”]。它的返回值是一个对象。
…mapState([“count”,”num1”,”num2”]):把一个对象进行“拆分”,称为拓展运算符。
整个来看:computed是一个属性名,属性值是一个对象,其中的组成是对mapState()这个函数的返回值进行拓展运算。这样就可以直接在组件内部把arr和amount当作计算属性来用。
2. Getters
Getters:仓库中的计算属性。
每一个Getters函数的第一个参数都是状态。
1. 在vuex定义getters:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
const store =new Vuex.Store({
// 开启严格模式
strick:true,
state:{
count:0,
age:12,
height:188,
list:[
{name:"az",score:46},
{name:"sx",score:24},
{name:"dc",score:50},
{name:"fv",score:78},
]
},
// 仓库中的计算属性
getters:{
// 每一个 getters 的第一个参数都是状态
failNumber(state){
let n=0;
state.list.forEach(item=>{
if(item.score<60){
n++;
}
})
return n;
}
},
});
export default store;
2.在组件中使用getters:
方法一:$store.getters.failedNumber
方法二 :mapGetters
与mapState类似,它的作用也是用来帮助我们去简化代码。我们如果直接定义一个计算属性也是可以的。
3. Mutations
Mutations:用来修改数据的唯一工具 ,可以追踪到状态变化。mutations函数的第一个参数是状态,每一个mutations都有commit,需要在组件中 用commit对数据进行修改。
在仓库中定义Mutations:
使用:
<template>
<div>
<p>我是add组件</p>
<p>在Add组件中使用仓库中的状态:{{ count }}</p>
<!-- <button @click="add">+1</button> -->
</div>
</template>
<script>
import { mapState, mapMutations } from "vuex"
import { ADD } from "../store/types"
export default {
// mapState 把仓库中的状态映射成计算属性
computed:{
// 自动映射
...mapState(["count"])
},
methods:{
// 法二:把仓库中的mutaion映射成组件的方法
// ...mapMutations(["add"]),
//法一:自己定义add函数通过commit改变数据
// add(){
// // this.$store.state.count++;
// // 通过mutaion来修改属性
// // 每一个mutaion都有一个commit
// this.$store.commit("add")
// }
}
}
</script>
4. Actions
在严格模式下,在mutations中写异步代码会警告,而且控制台不好追踪状态变rotu。可以将异步代码子写在Actions中,Actions中仅仅只是放异步代码,但是里面需要改变状态的唯一途径还是通过mutation,在组件中可以 dispatch一个mutation去改变数据。
虽然把异步操作写在actions中,但是改变状态的唯一方式是不变,还是通过mutations。
在 mutation 中混合异步调用会导致你的程序很难调试。
action类似于mutations,不同在于:
- actions 提交的是 mutations,而不是直接变更状态。
- actions 可以包含任意异步操作。
- action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,可以通过context.commit提交,也可以通过context.state获取state。
5. 小结
import {mapState,mapGetters,mapMutations,mapActions} from “vuex”;
map系列方法的作用(难点)。
我们之所以用 map系列的方法,是因为它可以帮助我们去简化代码。
不用map | 用map | |
---|---|---|
State | 在组件的计算属性中的使用。 computed:{ amount:function(){ return this.$store.state.amount; } } | Import {mapState} from “vuex” Computed{ …mapState([“amount”]), } |
Getters | computed:{ failedNumber:function(){ return this.$store.getters.failedNumber; } } | computed:{ …mapGetters([“failedNumber”]), } |
mutations | methods:{ add:function(obj){ return this.$store.commit(“add”,obj); } } | methods:{ …mapMutations([“add”]) } |
Actions | methods:{ add:function(obj){ return this.$store.dispatch(“add”,obj); } } | methods:{ …mapActions([“add”]) } |