前言
本篇博客主要回顾了vuex的相关操作。
面试回答
1.vuex:Vuex主要包含了state、getters、actions、mutations。按照日常使用,我们需要创建一个store类,store类分成两部分,一部分是构造函数,另外一部分是commit和dispatch方法。构造函数的主要工作是赋值以及响应式的处理,首先要对拿到的参数进行解构,分为state、getters、actions、mutations。然后把state和getters设置成响应式,这里实现响应式的方法可以用vue.observable或者用object.defineProperty设置get去实现,而getters需要先进行遍历。在这之后保存一下mutations和actions。接下来就是commit和dispatch的实现,这里简单一些,直接用传入的参数配合保存下来的mutations或者actions去执行对应的函数即可,当然因为state是单一数据源,如果要考虑mutations必须是同步任务,这里也可以对mutations的参数添加限制。最后vuex是通过vue.use进行注入,那么就需要提供一个install方法,在install方法中通过mixin以及beforeCreate生命周期将store注入vue实例组件。
知识点
Vuex 是一个专为Vue.js开发的状态管理模式。
1.state(数据中心)
单个数据:组件通过this.$store.state访问到所需数据
多个数据:mapState辅助函数,返回的是一个对象,通过展开运算符与其他数据进行混合
mapState({
count: state => state.count,
//传字符串参数'count'等同于state=>state.count
countAlias:'count',
//为了能够使用this获取局部状态,必须使用常规函数,也可以进行数据的计算
countPlusLocalState(state){
return state.count + this.localCount
}
})
本质上,可以通过$store.state.count++来改变count的值,之所以必须通过mutation改变store的值,是为了能被devTools监听记录,否则store被修改也不知道在哪被改的,如果遇到多处修改count,那么不易调试。
2.Getter
从state派生的数据,store中对数据进行计算处理的公共方法,相当于state的计算属性,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
-
store内
...action:{}, getters:{ countDoneTodos(state){ return state.count * 5 }, countLength(state,getters){ return getters.countDoneTodos.length } } //store.getters.countLength
-
组件内
export default { computed:{ //使用对象展开运算符将getter混入computed对象中 ...mapGetters([ 'countDoneTodos', 'countLength' ]) } } //this.$store.getters.countLength
3.Mutation
Mutation即同步任务处理中心,也是更改store中的状态的唯一方法,通过stire.commit(‘xxxx方法’,‘xxx参数’)。每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。
//Mutation方法
addCount(state,payload){
state.count = payload.count
state.age= payload.age
}
//发送对应的Mutation方法
this.$store.commit({
type:'addCount',
count:count,
age
})
//或通过映射来进行发送
import { mapMutaions } from 'vuex';
export default {
// ...
methods: {
...mapMutaions([
'addCount' // 映射 this.addCount() 为 this.$store.commit('addCount')
]),
}
}
4.Action
处理异步操作,并且返回promise,其内可以调用Mutation,commit更新store,如果是同步操作,可以直接通过mutation修改state。
//Action方法
actions:{
addCountAct({commit},data){
commit('addCount',data)
}
}
//发送对应的Action方法
this.$store.dispath({
type:'addCountAct',
count:count,
age
})
//或通过映射来进行发送
import { mapActions } from 'vuex';
export default {
// ...
methods: {
...mapActions([
actAdd:'addCountAct' // 映射 this.actAdd() 为 this.$store.dispath('addCountAct')
]),
}
}
5.Modules
将store进行分类,使用的时候this.$store.xxx.name
//xxx为modules的名称,commit一致,没有变化
//子store,test
export default{
namespaced:true,
state:{
message:'zxp'
},
mutation:{
changeMessage:(state,data)=>{
state.message = data
}
},
actions:{}
}
6.手写vuex
Vuex主要包含了state、getters、actions、mutations。按照日常使用,我们需要创建一个store类,store类分成两部分,一部分是构造函数,另外一部分是commit和dispatch方法。构造函数的主要工作是赋值以及响应式的处理,首先要对拿到的参数进行解构,分为state、getters、actions、mutations。然后把state和getters设置成响应式,这里实现响应式的方法可以用vue.observable或者用object.defineProperty设置get去实现,而getters需要先进行遍历。在这之后保存一下mutations和actions。接下来就是commit和dispatch的实现,这里简单一些,直接用传入的参数配合保存下来的mutations或者actions去执行对应的函数即可,当然因为state是单一数据源,如果要考虑mutations必须是同步任务,这里也可以对mutations的参数添加限制。最后vuex是通过vue.use进行注入,那么就需要提供一个install方法,在install方法中通过mixin以及beforeCreate生命周期将store注入vue实例组件。
import Vue from 'vue'
class Store {
constructor (options) {
const {
state = {},
getters = {},
mutations = {},
actions = {}
} = options
this.state = Vue.observable(state)
// 此处不直接 this.getters = getters,是因为下面的代码中要方法 getters 中的 key
// 如果这么写的话,会导致 this.getters 和 getters 指向同一个对象
// 当访问 getters 的 key 的时候,实际上就是访问 this.getters 的 key 会触发 key 属性的 getter
// 会产生死递归
this.getters = Object.create(null)
Object.keys(getters).forEach(key => {
Object.defineProperty(this.getters, key, {
get: () => getters[key](this.state)
})
})
this.mutations = mutations
this.actions = actions
}
commit (type, payload) {
// 执行this.mutations里对应函数
this.mutations[type](payload)
}
dispatch (type, payload) {
this.actions[type](payload)
}
}
const install = (Vue) => {
Vue.mixin({
beforeCreate() {
if (this.$options.store) { // 根组件
this.$store = this.$options.store
} else if (this.$parent && this.$parent.$store) { // 子组件
this.$store = this.$parent.$store
}
}
})
}
// 导出模块
const vuex = {
Store,
install
}
export default vuex
最后
走过路过,不要错过,点赞、收藏、评论三连~