详解几十行代码实现一个vue的状态管理

 更新时间:2019年01月28日 14:25:08   作者:Jike  
这篇文章主要介绍了详解几十行代码实现一个vue的状态管理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

介绍

采用集中式存储管理应用的所有组件的状态, 就能实现组件间数据共享

实现

逻辑图

从图上有两条线: Vue.use(vuec), 与 new Vuec.center(options)

第一条线Vue.use(vuec)安装插件

使用Vue.use(vuec)时, 会执行vuec的install方法,会注入参数Vue 所以vuec是这样的,

// index.js
import {Center, install} from './center'
export default {Center, install}

Center对象将实例化成center(下面再说),我们先看看install方法

// center.js
let Vue // 全局变量, 保存install里的Vue
export function install (_Vue) {
 if (!Vue) {
  _Vue.mixin({
   beforeCreate: applyMixin // 在beforeCreate钩子上混入applyMixin函数
  })
 }
 Vue = _Vue
}

install在Vue原型的beforeCreate混入applyMixin函数, 也就是说在生成每个Vue组件时,在它的生命周期beforeCreate钩子上就会执行applyMixin方法

第二条线 new Vuec.center(options)实例化Center对象

先看看用户传入的options, 下面例子

export default new Vuec.Center({
 state: {
  name: 'liuyang'
 },
 mutations: {
  changeName (state) {
   state.name = 'jike'
  }
 }
})

上面代码会生成center实例, 该实例上应该包括:state状态,commit方法提交变更等

// center.js
export class Center {
 constructor (options= {}) {
  let center = this
  this.mutations = options.mutations
  observeState(center, options.state)
 }
 get state () { // 代理了this.$center.state的最终访问值
  return this._vm.$data.$$state
 }
 commit (_type, _payload) {
  this.mutations[_type](this.state, _payload)
 }
}
function observeState(center, state) { // 响应式state
 center._vm = new Vue({
  data: {
   $$state: state
  }
 })
}

在执行new Vuec.Center({..})时,就是执行Center的构造函数

首先执行let center = this, 定义center保存当前实例

接着执行this.mutations = options.mutations, 在实例center上添加mutations属性, 值就是用户输入mutations,

按上面例子, this.mutations长成这样

this.mutations = {
  changeName (state) {
   state.name = 'jike'
  }
}

最后执行observeState(center, options.state), 作用:让center实例的state属性指向options.state并且是响应式的

  function observeState(center, state) { // 响应式state
   center._vm = new Vue({ // 利用Vue的响应系统,将state转化成响应式
    data: {
     $$state: state
    }
   })
  }

在center实例上添加_vm属性, 值是一个Vue实例, 在该Vue实例的data下定义了$$state, 它的值是options.state用户输入的state; 结合上面的这段代码

// center.js
export class Center {
 ...省略
 get state () { // 代理了this.$center.state的最终访问值
  return this._vm.$data.$$state
 }
 ...省略
}

所以我们在组件中访问center.state其实就是访问center._vm.$data.$$state

OK, center就构建好了

创建Vue组件

用户输入

import Vue from 'vue'
import App from './App'
import router from './router'
import center from './center'

new Vue({
 el: '#app',
 router,
 center, // 构建好的center实例
 template: '<App/>',
 components: {App}
})

在beforeCreate生命周期时会触发上面混入的applyMixin函数

// mixins.js
export default function applyMixin() {
 vuecInit.call(this) // 
}

function vuecInit () {
 const options = this.$options
 // vue的实例化是从外往内, 所以父组件的$center一定是options的center
 this.$center = options.parent?options.parent.$center: options.center
}

applyMixin里会执行vuecInit.call(this), 这里的this指向当前组件的实例,

接着看vuecInit, 定义了options等于用户输入选项,因为先创建根组件, 所以根组件this.$center的值的引用就是我们在new Vue({..center})时传入的center实例, 下面所有组件都指向它

OK, 你就可以在组件里使用this.$center访问了

commit变更

// center.js
export class Center {
 ... 省略
 commit (_type, _payload) {
  this.mutations[_type](this.state, _payload)
 }
}

通常我们变更时: this.$center.commit('changeName', 'jike'), 这样的话, this.mutations[_type]就是对应方法函数, 往该函数里传入state以及payload,

举上面的例子

// this.mutations[_type] , _type = 'changeName', payload= 'jike'
this.mutations = {
  changeName (state, payload) {
   state.name = payload
  }
}

说明

上面只是一个简单的状态管理, 还有很多地方没有实现: actions异步变更,getters函数,modules模块分割, 辅助函数mapState..等

源码地址: github

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 使用Vue封装一个自定义的右键菜单组件

    使用Vue封装一个自定义的右键菜单组件

    通过自定义右键菜单栏,用户可以根据自己的需求添加、调整和删除菜单选项,所以本文就来为大家介绍一下如何使用使用Vue封装一个自定义的右键菜单组件吧
    2024-01-01
  • vue3 + async-validator实现表单验证的示例代码

    vue3 + async-validator实现表单验证的示例代码

    表单验证可以有效的过滤不合格的数据,减少服务器的开销,并提升用户的使用体验,今天我们使用 vue3 来做一个表单验证的例子,需要的朋友跟随小编一起学习下吧
    2022-06-06
  • Vue CLI 3搭建vue+vuex最全分析(推荐)

    Vue CLI 3搭建vue+vuex最全分析(推荐)

    这篇文章主要介绍了Vue CLI 3搭建vue+vuex最全分析(推荐),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • vue项目之index.html如何引入JS文件

    vue项目之index.html如何引入JS文件

    这篇文章主要介绍了vue项目之index.html如何引入JS文件问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • VUE如何实现点击文字添加颜色(动态修改class)

    VUE如何实现点击文字添加颜色(动态修改class)

    这篇文章主要介绍了VUE如何实现点击文字添加颜色(动态修改class),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • vue2实现无感刷新token的方式详解

    vue2实现无感刷新token的方式详解

    在Web应用中,用户需要通过认证和授权才能访问受保护的资源,为了实现认证和授权功能,通常需要使用Token来标识用户身份并验证其权限,本文给大家介绍了vue2实现无感刷新token的方式,需要的朋友可以参考下
    2024-02-02
  • 浅谈vue websocket nodeJS 进行实时通信踩到的坑

    浅谈vue websocket nodeJS 进行实时通信踩到的坑

    这篇文章主要介绍了浅谈vue websocket nodeJS 进行实时通信踩到的坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • 详解在vue-cli项目中使用mockjs(请求数据删除数据)

    详解在vue-cli项目中使用mockjs(请求数据删除数据)

    本篇文章主要介绍了在vue-cli项目中使用mockjs(请求数据删除数据),具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • vue3 element-plus 实现表格数据更改功能详细步骤

    vue3 element-plus 实现表格数据更改功能详细步骤

    这篇文章主要介绍了vue3 element-plus实现表格数据更改功能,本文分步骤结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • vue如何监听页面的滚动的开始和结束

    vue如何监听页面的滚动的开始和结束

    这篇文章主要介绍了vue如何监听页面的滚动的开始和结束,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07

最新评论