深入Vue底层,手写一个vuex

Posted 欧阳呀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入Vue底层,手写一个vuex相关的知识,希望对你有一定的参考价值。


1. Vuex是什么?什么场景下使用?

  • Vuex是vue的一个插件,叫做状态管理模式,全局共享某一些状态
  • 通俗来讲,当各组件需要共享某一组状态的时候,会用到Vuex,兄弟组件及跨级组件传值也可以派上用场(如果数据量不大,或者组件状态不需要共享也可以用中央信息插件event-bus

2. Vuex的基本使用

  • vue-cli 4.0 以上,在搭建脚手架的时候选择此项就可以
  • 项目搭建完成,便会在src文件夹下看到一个store,这就是自动生成的仓库
  • 以下是vuex的一些基本操作,供参考:
import Vue from 'vue'
import Vuex from 'vuex'  
Vue.use(Vuex)

export default new Vuex.Store(   
  state:   
    name: 'Vuex',
    age: 18
  ,
  // 可以看做vuex的计算属性
  getters: 
    addName(state) 
      return `$state.name牛逼`
    
  ,
  // 提交数据更改
  mutations:     
    syncAdd(state, payload)
      state.age += payload
    ,
   
    syncReduce(state, payload)
      state.age -= payload
    
  ,
  // 处理异步,此处为异步提交数据
  actions:   
    asyncReduce(commit, payload)  
      setTimeout( () => 
        commit('syncReduce', payload)
      , 1000)
    
  ,
  // 管理多个模块,当vuex比较大的时候会用到
  modules: 
  
)
  • vue组件中的调用
<template>
  <div id="app">
    <h2>$store.state.name</h2>
    <div>$store.getters.addName</div>
    <div>年龄: $store.state.age</div>
    <div><button @click="add()">10</button></div>
    <div><button @click="reduce()">10-异步</button></div>
  </div>
</template>
<script>
export default 
  mounted () 
  	// 这里可以访问到 vuex中的整个store
    console.log(this.$store)
  ,
  methods: 
    // 同步加10
    add()
      this.$store.commit('syncAdd', 10)
    ,
    // 异步减2
    reduce() 
      // 会去找对应的action
      this.$store.dispatch('asyncReduce', 2)
    
  

</script>

3. 手写一个vuex

  • 从以上的应用,便可以反推出Vuex的基本源码
let Vue;
class Store 
    constructor(options = ) 
        // 实现响应式 核心(刚刚直接拿过用户的数组放上去,是没有响应式的)
        this.s = new Vue(
            data() 
                return  state: options.state 
            
        )

        // 将用户传入的getters放到store实例之上
        let getters = options.getters
        this.getters =  
        // 通过循环,拿出键值,绑定访问器属性get 劫持对象的所有属性
        Object.keys(getters).forEach((getterName) => 
            Object.defineProperty(this.getters,
            getterName, 
                get: () => 
                    // 执行此函数
                    return getters[getterName](this.state) 
                
            )
        )
        // 获取所有同步更新的操作方法
        let mutations = options.mutations 
        // 放到实例上去
        this.mutations = 
        // 订阅,下面commit是发布
        Object.keys(mutations).forEach( (mutationName)=> 
            // 当前实例上,通过名找方法
            this.mutations[mutationName] = (payload) =>
                // 内部的第一参数是状态
                mutations[mutationName](this.state, payload)
            
        )

        let actions = options.actions
        this.actions = 
        forEachFn(actions, (actionName, fn) => 
            this.actions[actionName] = (payload) => 
                // fn 是这个玩意 asyncReduce
                fn(this, payload)
            
        )

    
    // 提交更改,在当前store找到对应函数执行,通过名字找  发布
    commit = (mutationName, payload) => 
        this.mutations[mutationName](payload)
    
    // action 分发的方法
    dispatch = (actionName, payload) => 
        this.actions[actionName](payload)
    
    // 为了方便取值
    get state() 
        return this.s.state
    


const install = (_Vue) => 
    Vue = _Vue 
    Vue.mixin(
        beforeCreate() 
            console.log('beforeCreate')
            if (this.$options && this.$options.store)        // 根实例
                // 根实例增加$store属性
                this.$store = this.$options.store
             else 
                this.$store = this.$parent && this.$parent.$store
            

        
    )


export default 
    install, 
    Store

  • 总体思路就是在Vue实例上挂上一个store实例,使用Vue提供的install方法注入,之后将用户传入的都绑定上去即可

1. 希望本文能对大家有所帮助,如有错误,敬请指出

2. 原创不易,还请各位客官动动发财的小手支持一波(关注、评论、点赞、收藏)
3. 拜谢各位!后续将继续奉献优质好文
4. 如果存在疑问,可以私信我(主页有Q)

以上是关于深入Vue底层,手写一个vuex的主要内容,如果未能解决你的问题,请参考以下文章

深入Vue底层,手写一个vuex

深入Vue底层,手写一个vuex

手写Vuex源码

Vuex深入解读(适用于Vue2)

Vue 开发实战生态篇 # 17:Vuex核心概念及底层原理

手写RPC,深入底层理解整个RPC通信