Vuex是做什么的?
官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
简单解释:把需要多个组件共享的变量全部存储在一个对象里面,然后将这个对象放在顶层的Vue实例中,让其他组件可以使用,多个组件就可以共享这个对象中的所有变量属性。
Vuex就是为了提供这样一个在多个组件间共享状态的插件。
有什么状态是需要我们在多个组件间共享的呢?
• 如果你做过大型开放,你一定遇到过多个状态,在多个界面间的共享问题
• 比如用户的登录状态、用户名称、头像、地理位置信息等等
• 比如商品的收藏、购物车中的物品等等
• 这些状态信息,我们都可以放在统一的地方,对它进行保存和管理,而且它们还是响应式的
单界面的状态管理
State:就是我们的状态。(当做data中的属性)
View:视图层,可以针对State的变化,显示不同的信息
Actions:这里的Actions主要是用户的各种操作:点击、输入等等,会导致状态的改变
<template>
<div>
<h2>{{counter}}</h2>
<button @click="counter++">+</button>
<button @click="counter--">-</button>
</div>
</template>
<script>
export default{
name: 'helloworld',
data() {
return {
counter: 0
}
}
}
</script>
在这个案例中,个数counter的状态需要管理
• counter需要某种方式被记录下来,也就是我们的State
• counter目前的值需要被显示在界面中,也就是我们的View部分
• 界面发生某些操作时(我们这里是用户的点击,也可以是用户的input),需要去更新状态,也就是我们的Actions
多界面的状态管理
将共享的状态抽取出来,交给我们的大管家,统一进行管理,之后你们的每个试图,按照我规定好的规定,进行访问和修改等操作
- 安装插件
npm install vuex --save
- 如何使用(Vuex3)
①src下创建文件夹store,创建index.js
②import vue和vuex
③安装插件、创建对象、导出对象
//1.安装插件
Vue.use(Vuex)
//2.创建对象(使用vuex里面的store属性)
const store = new Vuex.Store({
state:{
counter: 100 //共享状态
}, //state保存状态,相当于变量
mutations:{
//方法,默认有一个参数state
increment(state){
state.counter++
}
}, //相当于计算属性 同步操作在这里
actions:{}, //异步操作发送网络在这里 再提交
getters:{},
modules:{}
})
//3.导出store对象
export default store
④在main.js中挂载store
import导入store,并且放在new Vue中写个store,在其他Vue组件中,我们就可以通过this.$store
的方式,获取到这个store对象了
⑤第一个组件中使用
在main.js挂载完之后所有的vue组件都有一个$store对象
<h2>{{$store.state.counter}}</h2>
⑥第二个组件中也想使用
<h2>{{$store.state.counter}}</h2>
- Devtools
跟踪state修改状态 - mutations
组件中使用mutations
<button @click="addition">+</button>
<script>
methods:{
addition() {
this.$store.commit('increment')
}
}
</script>
核心概念
- State
Vuex也使用了单一状态树来管理应用层级的全部状态,单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。 - Getters
getters类似于computed属性,当数据需要计算后显示的
<script>
getters:{
powerCount(state){
return state.counter * state.counter
}
}
</script>
<h2>{{$store.getters.powerCount}}</h2> <!--属性不需要加小括号-->
getters作为参数
<script>
getters:{
more20stu(state){
// 正常写
/* return state.students.filter(s => {
return s.age > 20
}) */
// 简写
return state.students.filter(s => s.age > 20)
},
more20stuLength(state,getters){
return getters.more20stu.length
}
}
</script>
<h2>{{ $store.getters.more20stu }}</h2>
<h2>{{ $store.getters.more20stuLength }}</h2>
getters默认是不能传递参数的,如果希望传递参数,那么只能让getters本身返回另一个函数
<script>
moreAgeStu(state){
//正常写法
/* return function (age){
return state.students.filter( s => s.age > age )
}*/
//箭头函数写法
return age => {
return state.students.filter( s => s.age > age )
}
}
</script>
<h2>{{ $store.getters.moreAgeStu(25) }}</h2>
- Mutation
Vuex的store状态的更新唯一方式:提交Mutation
Mutation主要包括两部分:
• 字符串的事件类型(type)
• 一个回调函数(handler),该回调函数的第一个参数就是state。
①Mutation传递参数
通过mutation更新
//有参数时,App.vue中
methods: {
addCount(count) {
this.$store.commit('incrementCount',count)
}
}
//index.js中
mutations: {
//方法
incrementCount(state, count){
state.counter += count
}
}
<button @click="addCount(5)">+5</button>
<button @click="addCount(10)">+10</button>
②Mutation提交风格
包含type属性的对象
this.$store.commit({
type: 'changeCount',
count: 100
})
Mutation中的处理方式是将整个commit的对象作为payload使用, 所以代码没有改变, 依然如下:
changeCount(state, payload){
state.count = payload.count
}
③Mutation响应规则(Vuex的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新)
提前在store中初始化好所需的属性(后添加的属性内容不是响应式的).
当给state中的对象添加新属性时, 使用下面的方式(vue2方法):
方式一:使用Vue.set(obj, 'newProp', 123) //三个参数:要改的对象,key(类型可以是字符串或number),value
方式二:用新对象给旧对象重新赋值state.info['height'] = payload.height
//index.js
state: {
info: {
name: 't',
age: 18,
height: 158
}
},
mutations: {
updateInfo(state){
//修改name属性内容。(是响应式的)
//state.info.name = 'ti'
//增加地址属性①。(vue2不是响应式的,vue3是响应式的)✔️
//state.info['address'] = '洛杉矶'
//增加地址属性②。(vue2是响应式的,vue3不是响应式的会报错不兼容Vue.set)
//Vue.set(state.info, 'address', '洛杉矶')
//删除属性①。(vue2不是响应式的,vue3是响应式的)✔️
delete state.info.age
//删除属性②。(vue2是响应式的,vue3不是响应式的会报错不兼容Vue.delete)
//Vue.delete(state.info, 'age')
}
}
//App.Vue
<p>{{ $store.state.info }}</p>
<button @click="updateInfo">修改信息</button>
methods: {
updateInfo(){
this.$store.commit('updateInfo')
}
}
④使用常量替代 Mutation 事件类型
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import { createStore } from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = createStore({
state: { ... },
mutations: {
// 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
[SOME_MUTATION] (state) {
// 修改 state
}
}
})
⑤Mutation必须是同步函数
- Action
Action类似于Mutation, 是用来代替Mutation进行异步操作的,默认参数context
Action方法可以返回promise,在另外一个地方用.dispatch拿到promise - Module
Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutation、action、getters等