【二十】vuex

本文详细介绍了Vuex在Vue.js中的应用,包括state(状态)、getters(计算属性)、actions(异步操作)和mutations(同步更新)。讲解了如何创建store、响应式处理、使用mapState/mapGetters/mapActions/mapMutations以及模块化的store结构,强调了状态管理的最佳实践。
摘要由CSDN通过智能技术生成

在这里插入图片描述

前言

本篇博客主要回顾了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

最后

走过路过,不要错过,点赞、收藏、评论三连~

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值