实现vuex原理的示例


Posted in Javascript onOctober 21, 2020

效果图如下:

实现vuex原理的示例

1. 准备好环境

使用 vue/cil 初始化项目配置:

npm install -g @vue/cli //全局安装@vue/cli vue create demo-vue //创建项目

yarn add vuex安装vuex创建一个store文件夹并使用:

实现vuex原理的示例

2. 实现目的

stroe/index.js内容如下:(我们的目的将引入自写的vuex实现vuex基础功能)

import Vue from 'vue'
import Vuex from 'vuex' 
// import Vuex from './myvuex'   //我们实现的 青铜版vuex
// import Vuex from './myvuexplus' //我们实现的 白银版vuex

Vue.use(Vuex) //执行install方法 将new Vuex.Store挂载到this.$store

export default new Vuex.Store({
 state: {
  counter: 0,
  userData: {
   name: '时间',
   age: 18
  }
 },
 getters: {
  name(state) {
   return state.userData.name
  }
 },
 mutations: {
  add(state) {
   state.counter++
  },
  updateName(state, payload) {
   state.userData.name = payload
  }
 },
 actions: {
  add({ commit }) {
   setTimeout(() => {
    commit('add')
   }, 1000);
  }
 }
})
  • 青铜版vuexmyvuex.js代码如下:
let Vue
class Store {
 constructor(options) {
  this._vm = new Vue({
   data: {
    state: options.state
   }
  })

  let getters = options.getters
  this.getters = {}
  Object.keys(getters).forEach((val) => {
   Object.defineProperty(this.getters, val, { //getters响应式
    get: () => {
     return getters[val](this.state)
    }
   })
  })

  this._actions = Object.assign({}, options.actions)
  this._mutations = Object.assign({}, options.mutations)
 }

 // get/set state目的:防止外部直接修改state
 get state() {
  return this._vm.state
 }
 set state(value) {
  console.error('please use replaceState to reset state')
 }

 commit = (funName, params) => { //this执行问题
  // 在mutations中找到funName中对应的函数并且执行
  this._mutations[funName](this.state, params)
 }

 dispatch(funName, params) {
  this._actions[funName](this, params)
 }
}

function install(vue) {
 Vue = vue
 vue.mixin({
  beforeCreate () {
   // 将 new Store() 实例挂载到唯一的根组件 this 上
   if (this.$options?.store) {
    this.$store = this.$options.store
   } else {
    this.$store = this.$parent && this.$parent.$store
   }
  }
 })
}

export default {
 Store,
 install
}

青铜版vuex this.$stroe:

实现vuex原理的示例

  • 白银版vuexmyvuexplus.js代码如下:
let _Vue
const install = function(Vue, opts) {
 _Vue = Vue
 _Vue.mixin({ // 因为我们每个组件都有 this.$store这个东西,所以我们使用混入模式
  beforeCreate () { // 从根组件向子组件遍历赋值,这边的 this 就是每个 Vue 实例
   if (this.$options && this.$options.store) { // 这是根节点
    this.$store = this.$options.store
   } else {
    this.$store = this.$parent && this.$parent.$store
   }
  }
 })
}

class ModuleCollection {
 constructor(opts) {
  this.root = this.register(opts)
 }

 register(module) {
  let newModule = {
   _raw: module,
   _state: module.state || {},
   _children: {}
  }
  Object.keys(module.modules || {}).forEach(moduleName => {
   newModule._children[moduleName] = this.register(module.modules[moduleName])
  })
  return newModule
 }
}

class Store {
 constructor(opts) {
  this.vm = new _Vue({
   data () {
    return {
     state: opts.state // 把对象变成响应式的,这样才能更新视图
    }
   }
  })

  this.getters = {}
  this.mutations = {}
  this.actions = {}

  // 先格式化传进来的 modules 数据
  // 嵌套模块的 mutation 和 getters 都需要放到 this 中
  this.modules = new ModuleCollection(opts)
  console.log(this.modules)

  Store.installModules(this, [], this.modules.root)
 }

 commit = (mutationName, value) => { // 这个地方 this 指向会有问题,这其实是挂载在实例上
  this.mutations[mutationName].forEach(f => f(value))
 }

 dispatch(actionName, value) {
  this.actions[actionName].forEach(f => f(value))
 }

 get state() {
  return this.vm.state
 }
}
Store.installModules = function(store, path, curModule) {
 let getters = curModule._raw.getters || {}
 let mutations = curModule._raw.mutations || {}
 let actions = curModule._raw.actions || {}
 let state = curModule._state || {}

 // 把子模块的状态挂载到父模块上,其他直接挂载到根 store 上即可
 if (path.length) {
  let parent = path.slice(0, -1).reduce((pre, cur) => {
   return pre[cur]
  }, store.state)
  _Vue.set(parent, path[path.length - 1], state)
 }

 Object.keys(getters).forEach(getterName => {
  Object.defineProperty(store.getters, getterName, {
   get: () => {
    return getters[getterName](state)
   }
  })
 })

 Object.keys(mutations).forEach(mutationName => {
  if (!(store.mutations && store.mutations[mutationName])) store.mutations[mutationName] = []
  store.mutations[mutationName].push(value => {
   mutations[mutationName].call(store, state, value)
  })
 })

 Object.keys(actions).forEach(actionName => {
  if (!(store.actions && store.actions[actionName])) store.actions[actionName] = []
  store.actions[actionName].push(value => {
   actions[actionName].call(store, store, value)
  })
 })

 Object.keys(curModule._children || {}).forEach(module => {
  Store.installModules(store, path.concat(module), curModule._children[module])
 })


}

// computed: mapState(['name'])
// 相当于 name(){ return this.$store.state.name }
const mapState = list => { // 因为最后要在 computed 中调用
 let obj = {}
 list.forEach(stateName => {
  obj[stateName] = () => this.$store.state[stateName]
 })
 return obj
}

const mapGetters = list => { // 因为最后要在 computed 中调用
 let obj = {}
 list.forEach(getterName => {
  obj[getterName] = () => this.$store.getters[getterName]
 })
 return obj
}

const mapMutations = list => {
 let obj = {}
 list.forEach(mutationName => {
  obj[mutationName] = (value) => {
   this.$store.commit(mutationName, value)
  }
 })
 return obj
}

const mapActions = list => {
 let obj = {}
 list.forEach(actionName => {
  obj[actionName] = (value) => {
   this.$store.dispatch(actionName, value)
  }
 })
 return obj
}

export default {
 install,
 Store,
 mapState,
 mapGetters,
 mapMutations,
 mapActions
}

白银版vuex this.$stroe:

实现vuex原理的示例

3. App.vue 内使用自写的vuex:

<template>
 <div id="app">
  <button @click="$store.commit('add')">$store.commit('add'): {{$store.state.counter}}</button>
  <br>
  <button @click="$store.commit('updateName', new Date().toLocaleString())">$store.commit('updateName', Date): {{$store.getters.name}}</button>
  <br>
  <button @click="$store.dispatch('add')">async $store.dispatch('add'): {{$store.state.counter}}</button>
 </div>
</template>
<script>
...

以上就是实现vuex原理的示例的详细内容,更多关于实现vuex原理的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
纯JAVASCRIPT图表动画插件Highcharts Examples
Apr 16 Javascript
jQuery操作select的实例代码
Jun 14 Javascript
遍历DOM对象内的元素属性示例代码
Feb 08 Javascript
纯js实现遮罩层效果原理分析
May 27 Javascript
javascript中sort()的用法实例分析
Jan 30 Javascript
js removeChild 方法深入理解
Aug 16 Javascript
使用bat打开多个cmd窗口执行gulp、node
Feb 17 Javascript
Angular客户端请求Rest服务跨域问题的解决方法
Sep 19 Javascript
Vue中使用webpack别名的方法实例详解
Jun 19 Javascript
js核心基础之构造函数constructor用法实例分析
May 11 Javascript
基于Vue el-autocomplete 实现类似百度搜索框功能
Oct 25 Javascript
JS数组push、unshift、pop、shift方法的实现与使用方法示例
Apr 29 Javascript
详解JavaScript类型判断的四种方法
Oct 21 #Javascript
node.js如何根据URL返回指定的图片详解
Oct 21 #Javascript
vue中template的三种写法示例
Oct 21 #Javascript
Vue使用v-viewer实现图片预览
Oct 21 #Javascript
UEditor 自定义图片视频尺寸校验功能的实现代码
Oct 20 #Javascript
Vue+axios封装请求实现前后端分离
Oct 23 #Javascript
构建一个JavaScript插件系统
Oct 20 #Javascript
You might like
加强版phplib的DB类
2008/03/31 PHP
php中in_array函数用法探究
2014/11/25 PHP
php 运算符与表达式详细介绍
2016/11/30 PHP
PHP const定义常量及global定义全局常量实例解析
2020/05/28 PHP
PHP笛卡尔积实现原理及代码实例
2020/12/09 PHP
jQuery实现切换页面布局使用介绍
2011/10/09 Javascript
关于js数组去重的问题小结
2014/01/24 Javascript
让浏览器DOM元素最后加载的js方法
2014/07/29 Javascript
JQuery Tips相关(1)----关于$.Ready()
2014/08/14 Javascript
纯JavaScript实现的兼容各浏览器的添加和移除事件封装
2015/03/28 Javascript
ECMAScript6中Map/WeakMap详解
2015/06/12 Javascript
JS及PHP代码编写八大排序算法
2016/07/12 Javascript
JavaScript实现向select下拉框中添加和删除元素的方法
2017/03/07 Javascript
vue的事件绑定与方法详解
2017/08/16 Javascript
原生js实现自定义消息提示框
2020/11/19 Javascript
[44:15]国士无双DOTA2 6.82版本详解(上)
2014/09/28 DOTA
[01:21:36]CHAOS vs Alliacne 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
[55:39]DOTA2-DPC中国联赛 正赛 VG vs LBZS BO3 第二场 1月19日
2021/03/11 DOTA
python使用PyGame播放Midi和Mp3文件的方法
2015/04/24 Python
Python实现提取谷歌音乐搜索结果的方法
2015/07/10 Python
Python实现的单向循环链表功能示例
2017/11/10 Python
使用Django连接Mysql数据库步骤
2019/01/15 Python
django中间键重定向实例方法
2019/11/10 Python
python通过opencv实现图片裁剪原理解析
2020/01/19 Python
Python requests模块cookie实例解析
2020/04/14 Python
django跳转页面传参的实现
2020/09/17 Python
HTML5 中新的全局属性(整理)
2013/07/31 HTML / CSS
英国家喻户晓的折扣商场:TK Maxx
2017/05/26 全球购物
志愿者爱心公益活动策划方案
2014/09/15 职场文书
党员教师个人对照检查材料(群众路线)
2014/09/26 职场文书
共青团员自我评价
2015/03/10 职场文书
反腐倡廉主题教育活动总结
2015/05/07 职场文书
财务人员入职担保书
2015/09/22 职场文书
员工保密协议范本,您一定得收藏!很有用!
2019/08/08 职场文书
Spring Boot配合PageHelper优化大表查询数据分页
2022/04/20 Java/Android
python数据分析之单因素分析线性拟合及地理编码
2022/06/25 Python