一、Vuex是什么?
官方解释为:Vuex是一个转为Vue.js应用程序开发的状态管理模式。
- 它采用
集中式存储管理
应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。- Vuex也集成了Vue官方调试工具
devtools extension
,提供了诸如零配置的time-travel
调试、状态快照导入导出等高级调试功能。
通俗点来说,他就是个单例,任何一个用到单例中同一变量的地方,只要有一处修改了变量的值,其他的地方也会响应式的变化,最终保持一致。
我们把需要共享的状态(变量)抽取出来,交给Vuex统一管理,然后我们按照规定好的规则,进行访问和修改等操作;这就是Vuex背后的基本思想。
Backend API.png
二、Vuex的引入和使用
这里以webpack@3.6.0为例
npm install vuex@3.6.2 --save
- 类似于vue-router在文件src下创建store文件夹,然后在其中创建
index.js
文件
import Vue from "vue"
import Vuex from 'vuex'
//1、安装插件
Vue.use(Vuex)
//2、创建对象
const store = new Vuex.Store({
state:{
},
//修改state对象的话,至少要经过mutations中的方法
mutations:{
},
//异步延时操作
actions:{
},
getters:{//类似于计算属性
},
modules:{
}
})
//3、导出store对象
export default store
- 然后在在main.js中使用即可
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
render: h => h(App)
})
注意:这里的store好像一定要取这个名,我试了一下其他的,好像拿不到值;很奇怪!!!
三、Vuex核心概念
1、State-单一状态树
单一状态树:英文名称Single Source of Truth,也可以翻译成单一数据源。
Vuex使用了单一状态树来管理应用层级的全部状态。
单一状态树能够让以我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。
state:{
counter:200,
students:[
{id:100,name:'zhangsan',age:18},
{id:101,name:'lisi',age:10},
{id:102,name:'wangwu',age:23},
{id:103,name:'zhaoliu',age:33}
]
},
这里以展示counter为例
组件中使用为:$store.state.counter
2、Getters
可以把他的作用理解成计算属性。
- 1、如我们需要展示counter的平方 ,我们在getters中添加一下方法;
powerCounter(state){
return state.counter * state.counter
},
并在相应的组件中使用:$store.getters.powerCounter
- 2、展示年龄大于15岁的学生,getters中添加方法
more15stu(state){
return state.students.filter(s => s.age > 15)
},
组件中使用:$store.getters.more15stu
- 3、getters作为参数,年龄大于15岁学生的个数
more15stulength(state,getters){
return getters.more15stu.length
},
使用:$store.getters.more15stulength
- 4、传递参数,年龄为参数age,展示大于年龄age的学生信息
moreagestu(state){//传参
return age => {
return state.students.filter(s => s.age > age)
}
}
注意:传递参数时,返回一个带有入参的函数。
使用:$store.getters.moreagestu(19)
3、Mutations
Vuex的store状态的状态更新唯一方式:提交mutations
通常情况下,Vuex要求我们Mutations中方法必须是同步函数。
- 主要原因是当我们使用devtools时,devtools可以帮助我们捕捉mutations的快照。
- 但是如果是异步操作,那么devtools将不能很好的追踪这个操作什么时候被完成。
3.1、基本用法
如在App.vue组件中通过点击按钮来加减counter
- 先在mutations定义以下两个方法
increment(state){
state.counter++
},
decrement(state){
state.counter--
}
- 然后在组件中使用
<template>
<div id="app">
<button @click="addition">+</button>
<button @click="subraction">-</button>
</div>
</template>
<script>
export default {
name: 'App',
methods:{
addition(){
this.$store.commit('increment')
},
subraction(){
this.$store.commit('decrement')
}
}
}
</script>
<style>
</style>
通过事件来调用this.$store.commit('increment')
3.2、带参
参数被称为是mutations的载荷(payload)
- 可以是一个数字
mutations:{
incrementCount(state,count){
state.counter += count
}
},
使用:
addition(){
this.$store.commit('incrementCount',10)
},
- 也可以是一个对象
mutations:{
addStudent(state,stu){
state.students.push(stu)
}
},
用法:
addition(){//方法名可以随便哈,我这里只是懒的写了
const stu = {id:144,name:'kk',age:49}
this.$store.commit('addStudent',stu)
},
3.3、特殊提交风格
提交
this.$store.commit({
type:'changeCount',
count
})
将整个commit对象作为payload来使用
changeCount(state,payload){
state.count += payload.count
}
3.4、响应规则
- 提前在store中初始化好所需属性的
添加新属性方式:使用Vue.set(obj,'newProp',123)
state:{
info:{id:120,name:'kk',age:33}
},
//修改state对象的话,至少要经过mutations中的方法
mutations:{
addprops(state){//添加属性
Vue.set(state.info,'address','开封')
},
delectprops(state){//删除属性
Vue.delete(state.info,'age')
}
},
3.5、mutations常量类型
- 随着项目的越来越大,在mutations中我们定义方法也就越来越多。
- 方法多了,我们往往会记不住,且还需要多个文件之间来回的切换,不复制的情况下还容易写错,所以这里引入了常量类型来管理
在store文件目录下,创建mutations-type.js
export const INCREMENT = 'increment'
在index.js中引入、定义
import {INCREMENT} from './mutations-types.js'
[INCREMENT](state){
state.counter++
},
在组件中使用
import {INCREMENT} from './mutations-types.js'
addition(){
this.$store.commit(INCREMENT)
},
4、Action
Action类似于Mutations,但是是用来替代Mutations进行异步操作的。
一段时间后再做某项操作
mutations: {
[INCREMENT](state) {
state.counter++
},
},
//异步操作
actions: {
asyAdd(context) {
setTimeout(() => {
content.commit(INCREMENT)
},1000)
}
},
这里的context对应的就是store对象
通过this.$store.dispatch('asyAdd')
调用。
带参:
asyAdd(context,payload)
、his.$store.dispatch('asyAdd',abc)
- 异步且有回调能知道什么时候有结果的
asyAdd(context,payload) {
return new Promise((resolve,reject) => {
content.commit(INCREMENT)
console.log(payload);
resolve()
})
}
this.$store.dispatch('asyAdd','我是携带的参数').then(res => {
console.log('异步操作已完成');
console.log(res);
})
5、Modules
项目越大、store对象管理的状态也会越来越多,从而会变得很臃肿,module就是将store分割成不同的模块,有着自己的state、mutations、actions、getters.
const moduleA = {
state:{
name:'abc'
},
mutations:{
updataName(state,payload){
state.name = payload
}
},
actions:{
aupNname(context){
setTimeout(() => {
context.commit('updataName','lisi')//
},1000)
}
},
getters:{
fullname(state){
return state.name + '1111'
},
fullname1(state,getters,rootState){
return getters.fullname + rootState.counter
}
},
}
modules: {
a:moduleA
}
- 通过
$store.state.a.name
获取a中state里面name的值。- 同样是通过
this.$store.commit('updataName','lisi')
来修改name的值- 同样是通过
$store.getters.fullname
来展示;但可以多了rootState
参数。- actions还是以
this.$store.dispatch('aupNname')
调用;但是这里面的context和rootState里面actions里面的context是不一样的。
网友评论