Vuex
Vuex是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
简单来说vuex就是一个全局状态的管理,和全局变量有很多相似之处。
那么它和全局变量有什么区别呢?
Vuex的核心就是store,它里面存贮着你的项目中的大部分state。并且它以一定的规则约束你去修改这些变量,而不是像全局变量一样随意修改,不安全。
安装
我个人推荐用npm或者yarn进行安装
npm install vuex@next --save //npm安装
yarn add vuex@next --save //yarn安装
核心概念(state,getter,mutations,actions,modules)
state
state就是一个全局状态的初始化,里面可以定义你想定义的全局状态量,他们都储存在store中并且Vuex的状态储存都是响应式的。比如:
state: {
count: 1,
num:2
}
如果我们想在其他的vue文件中获取这个count的值,我们就要这样写:
import {useStore} from "vuex";
const store = useStore()
const count = store.state.count
console.log(store.state.count) // 1
同样想获取num也是一个道理。
mutation
提交mutation是更新store中state的唯一方法。每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,比如我们定义了一个mutations:
mutations: {
setCount(state, num) {
state.count = num;
}
}
此时我们的回调函数是setCount。但是呢,我们无法直接调用这个函数。此时我们就要提交mutation(也就是commit mutation),从store中调用我们的setCount:
setCount就是我们的事件类型,10就是向store中传入的额外参数,即mutation的荷载(payload)。
这里我做了一个@click的事件并在store.commit前后都打印值,来更好地理解这个值的变化。
第一次点击打印:
第二次点击打印:
我们可以清楚的看到第一次打印时,原来是1,然后经过更改后变成了10,第二次打印两次都是10。说明此时store里面存储的状态的count发生了改变,并再次存入store中。
我们还可以以对象的风格提交
store.commit({
type:'setCount',
amount:100
})
我们可以猜一下,我们再次打印store.state.count会发生什么?
此时它返回的是一个proxy对象,我们必须还得在后面加个.count才能获取到我们100这个值。假如我们先写的普通方式提交,再写对象风格的提交,store里面最后也会变成对象的形式,就如同上图。
action
1、类似于mutation,但是action可以异步操作,更改数据还是到mutations中更改。我们来写个简单的action:
actions: {
setCountPromise(context,num){
return new Promise((resolve, reject)=>{
if (num>100){
reject("值不能大于100")
}else {
context.commit("setCount",num)
resolve('111')
}
})
}
}
我们这里返回了一个promise来校验num的值是否大于100。action函数有一个context对象,此对象和store实例差不多,具有相同的方法和属性,因此我们可以调用context.commit提交一个mutation。肯定很多人好奇context是什么我们来打印一下context
可以看到里面有许多的方法和对象。因此我们可以通过context.state和context.getters来获取state 和 getters。
2、分发Action
Action 通过 store.dispatch 方法触发:
store.dispatch('setCountPromise', 100).then(res => {
alert('修改成功'+ res)
}).catch(err => {
alert(err)
})
大家可能会很好奇这个和mutation不是没什么区别吗?区别就在于它可以异步实现啊,这就是我们为什么写了一个promise来作为示例。
getter
getter的作用就是计算state,来获取我们想要的值。
直接上例子:
getters: {
countState(state){
return state.count>=1
}
},
我们这边写一个countstate的方法来计算state.count的值是否大于1,大于1就返回true,否则为false,并在分发action前后都打印一下countstate的值:
console.log(store.getters.countState)
const handelLogin = () => {
store.dispatch('setCountPromise', 100).then(res => {
alert('修改成功'+ res)
}).catch(err => {
alert(err)
})
console.log(store.getters.countState)
此时我们把值修改为100,返回的肯定就是true。如果我们把100修改为-100,返回的就是false。这边比较简单就不演示给大家看了。
modules
modules就是当我们的数据比较多的时候,我们要把数据分模块来写,每个模块有自己的state、mutation、action 和getter,这样比较方便读写,也方便我们管理我们的代码,不至于代码臃肿。
这边我们先在store中创建一个目录,再在目录中创建一个js文件,我们把之前写的state、mutation、action 和getter都存在里面。记得导出就行。之后我们再在源文件中导入我们新建的文件。
import user from "./state/numState"
modules: {
user
}
})
此时如果我们想要获取count的值就要写成store.state.user.count,因为我们之前在state里面储存的数据都被放到了state.user里面,如图:
然而获取getter里面countstate的值还是直接写store.count。