手写vuex

vuex

基本用法

vuex是作为插件使用,Vue.use(vuex)

最后注册给new Vue的是一个new Vuex.Store实例

// store.js
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex) // Vue.use注册插件
// new Vuex.Store实例
export default new Vuex.Store({
  state: {},getters: {},mutations: {},actions: {},modules: {}
})// main.js
import store from './store'new Vue({
  router,
  store,render: h => h(App)
}).$mount('#app')

根实例 组件

比如这里,App是vue实例的子组件即渲染组件

import App from './App.vue'
import store from './store'new Vue({
  router,
  store, // 每个子组件都有$store
  render: h => h(App)
}).$mount('#app')

getters:注册参数state

mutation: (state, payload)

actions: ({ commit, dispatch }, payload)

?模板编译语法

手写vuex: install

install:接收注入的参数Vue,那么这个插件就是不需要依赖于Vue的。

store是通过根组件传入进去的

通过Vue.mixin

main->app->xxx

main.js中创建实例,app.vue

也说明组件的渲染是从父到子

export default function applyMixin (Vue) {
  Vue.mixin({
    beforeCreate: vueInit
  })
}
function vueInit () {
  const options = this.$options
  if (options.store) {
    this.$store = options.store
  } else if (options.parent && options.parent.$store) {
    this.$store = options.parent.$store
  }
  // console.log('vueInit', this, this.$options.name)
}

状态实现 & 基本版实现

state实现:

getters实现:

借用computed。return结果不变,函数不会重新执行。

export default {data () {return {}},computed: {a () {return 'xxx'}}
}

mutations(actions同):

import applyMixin from './mixin'
let Vue
export class Store {constructor (options) {const state = options.stateconst getters = options.gettersconst computed = {}
    this.getters = {}Object.keys(getters).forEach(key => {const fn = getters[key]
      computed[key] = () => fn(this.state) // 注入state参数Object.defineProperty(this.getters, key, {
        get: () => {return this._vm[key]}})})    this._vm = new Vue({
      data: {$$state: state},
      computed})const mutations = options.mutationsconst actions = options.actions
    this.mutations = {}
    this.actions = actionsObject.keys(mutations).forEach(key => {const fn = mutations[key]
      this.mutations[key] = (payload) => fn(this.state, payload)})Object.keys(actions).forEach(key => {const fn = actions[key]
      this.actions[key] = (payload) => fn(this, payload)})const commit = (type, payload) => {
      this.mutations[type](payload)}const dispatch = (type, payload) => {
      this.actions[type](payload)}// this.commit = commit
    this.dispatch = dispatch}  commit=(type, payload) => {
    this.mutations[type](payload)}  get state () {return this._vm._data.$$state}
}
export const install = (_Vue) => {
  Vue = _VueapplyMixin(Vue)
}

模块划分*

namespaced: false

state会合并:

state:{

age:18,

a:{

age:28

},

b:{

age:58

}

}

mutations会把同名的组合成一个数组,然后commit的时候全部触发

模块安装*

实现Module类

installModule

import applyMixin from './mixin'
import ModuleCollection from './module/module-collection'
const installModule = (store, rootState, path, module) => {
  module.forEachMutation((mutation, key) => {
    store._mutations[key] = store._mutations[key] || []
    store._mutations[key].push((payload) => {
      mutation.call(store, module.state, payload)
    })
  })
  module.forEachAction((action, key) => {
    store._actions[key] = store._actions[key] || []
    store._actions[key].push((payload) => {
      action.call(store, store, payload)
    })
  })
  module.forEachGetter((getter, key) => {
    store._wrappedGetters[key] = () => {
      return getter.call(store, module.state)
    }
  })
  module.forEachChild((child, key) => {
    installModule(store, rootState, path.concat(key), child)
  })
}
let Vue
export class Store {
  constructor (options) {
    const state = options.state
    /**
     * 对数据进行格式化操作:递归形成了一棵树
     */
    this._module = new ModuleCollection(options)
    console.log('this._module===', this._module)
    this._mutations = {}
    this._actions = {}
    this._wrappedGetters = {}
    installModule(this, state, [], this._module.root)
    // const getters = options.getters
    // const computed = {}
    // this.getters = {}
    // Object.keys(getters).forEach(key => {
    //   const fn = getters[key]
    //   computed[key] = () => fn(this.state) // 注入state参数
    //   Object.defineProperty(this.getters, key, {
    //     get: () => {
    //       return this._vm[key]
    //     }
    //   })
    // })
    //
    // this._vm = new Vue({
    //   data: {
    //     $$state: state
    //   },
    //   computed
    // })
    // const mutations = options.mutations
    // const actions = options.actions
    // this.mutations = {}
    // this.actions = actions
    // Object.keys(mutations).forEach(key => {
    //   const fn = mutations[key]
    //   this.mutations[key] = (payload) => fn(this.state, payload)
    // })
    // Object.keys(actions).forEach(key => {
    //   const fn = actions[key]
    //   this.actions[key] = (payload) => fn(this, payload)
    // })
    // const commit = (type, payload) => {
    //   this.mutations[type](payload)
    // }
    // const dispatch = (type, payload) => {
    //   this.actions[type](payload)
    // }
    // // this.commit = commit
    // this.dispatch = dispatch
  }  // commit=(type, payload) => {
  //   this.mutations[type](payload)
  // }  get state () {
    return this._vm._data.$$state
  }
}
export const install = (_Vue) => {
  Vue = _Vue
  applyMixin(Vue)
}

import { forEachValue } from '@/vuex/utils'export default class Module {
  constructor (options) {
    this._raw = options
    this._children = {}
    this.state = options.state
  }  getChild (moduleName) {
    return this._children[moduleName]
  }  addChild (moduleName, newModule) {
    this._children[moduleName] = newModule
  }  forEachMutation (fn) {
    if (this._raw.mutations) {
      forEachValue(this._raw.mutations, fn)
    }
  }  forEachAction (fn) {
    if (this._raw.actions) {
      forEachValue(this._raw.actions, fn)
    }
  }  forEachGetter (fn) {
    if (this._raw.getters) {
      forEachValue(this._raw.getters, fn)
    }
  }  forEachChild (fn) {
    forEachValue(this._children, fn)
  }
}

模块的状态*

命名空间的实现

注册的是时候加上namespaced

vuex插件的使用

辅助函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/13757.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【树链剖分+MST】CF609E

Problem - E - Codeforces 题意: 思路: 先把全局的MST求出来,然后对于一条边,如果它本来就在MST中,说明代价就是MST的权值和,否则它加入MST中,此时MST形成了环,我们把环中最大的那…

docker安装rabbitmq

1,拉取rabbitmq容器 docker pull rabbitmq 2,下载完以后启动容器 先查看自己的容器id: [rootch ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE rabbitmq latest bcef1e…

Power BI-网关设置与云端报表定时刷新(一)

网关的工作原理 网关是将本地数据传输至云端的桥梁,不仅Power BI能使用,其他微软软件也能够使用。 我们发布在云上的报表,发布后是静态的,不会自动刷新。需要通过网关设置定时刷新。 安装与设置 1.登录到Powerbi 在线服务–设置…

实战项目——基于多设计模式下的同步异步日志系统

系列文章目录 1.项目介绍 2.相关技术补充 3.日志系统框架 4.代码设计 5.功能测试 6.性能测试 文章目录 目录 系列文章目录 1.项目介绍 2.相关技术补充 3.日志系统框架 4.代码设计 5.功能测试 6.性能测试 文章目录 前言 一、项目介绍 二、开发环境 三、核心技…

Ubuntu更改虚拟机网段(改成桥接模式无法连接网络)

因为工作需要,一开始在安装vmware和虚拟机时,是用的Nat网络。 现在需要修改虚拟机网段,把ip设置成和Windows端同一网段,我们就要去使用桥接模式。 环境: Windows10、Ubuntu20.04虚拟机编辑里打开虚拟网络编辑器&#…

7.Docker-compose

文章目录 Docker-compose概念Docker-compose部署YAML文件格式和编写注意事项注意数据结构对象映射序列属组布尔值序列的映射映射的映射JSON格式文本换行锚点和引用 Docker compose配置常用字段docker compose常用命令Docker Compose 文件结构docker compose部署apachedocker co…

Ubuntu Server版 之 mysql 系列(-),安装、远程连接,mysql 创建用户、授权等

Ubuntu 分 桌面版 和 服务版 桌面版 :有额外的简易界面 服务版:是纯黑框的。没有任何UI界面的可言 安装mysql 安装位置 一般按照的位置存放在 /usr/bin 中 sudo apt-get install mysql-server退出程序或应用 exit 或 Ctrl D 查看mysql的状态 servic…

springboot参数校验

springboot参数传递 PathVariableRequestParamRequestBody JSR303 jsr303 : 也称 bean validation 规范,用于java bean 验证的标准API,,他定义了一组注解,可以在javabean 的属性上声明验证规则 JSR: ja…

【Android安全】Embedded Trace Microcell模块

ETM: Embedded Trace Macrocell, hardware unit responsible to generate hardware instruction trace. ETM模块用于在硬件层面实现instruction trace,可用于辅助逆向分析。 使用教程: https://mcuoneclipse.com/2016/11/05/tutorial-getting-etm-inst…

鸿鹄协助管理华为云与炎凰Ichiban

炎凰对华为云的需求 在炎凰日常的开发中,对于服务器上的需求,我们基本都是采用云服务。目前我们主要选择的是华为云,华为云的云主机比较稳定,提供的云主机配置也比较多样,非常适合对于不同场景硬件配置的需求&#xff…

Java IO,BIO、NIO、AIO

操作系统中的 I/O 以上是 Java 对操作系统的各种 IO 模型的封装,【文件的输入、输出】在文件处理时,其实依赖操作系统层面的 IO 操作实现的。【把磁盘的数据读到内存种】操作系统中的 IO 有 5 种: 阻塞、 非阻塞、【轮询】 异步、 IO复…

NLP From Scratch: 生成名称与字符级RNN

NLP From Scratch: 生成名称与字符级RNN 这是我们关于“NLP From Scratch”的三个教程中的第二个。 在<cite>第一个教程< / intermediate / char_rnn_classification_tutorial ></cite> 中&#xff0c;我们使用了 RNN 将名称分类为来源语言。 这次&#xff…

Java泛型

文章目录 1. 泛型入门1.1 定义简单泛型类1.2 泛型方法1.3 限定类型变量 2. 擦除和转换2.1 类型擦除 3. 类型通配符3.1 通配符上限3.2 通配符下限3.3 例子 4. java的Type4.1 UML总览 1. 泛型入门 泛型的英文名Generic&#xff0c;java5以后&#xff0c;引入参数化类型&#xff…

原型模式——对象的克隆

1、简介 1.1、概述 可以通过一个原型对象克隆出多个一模一样的对象&#xff0c;该模式被称为原型模式。 在使用原型模式时&#xff0c;需要首先创建一个原型对象&#xff0c;再通过复制这个原型对象来创建更多同类型的对象。 1.2、定义 原型模式&#xff08;Prototype Patt…

14.python设计模式【模板方法模式】

内容&#xff1a;定义一个操作中的算法的骨架&#xff0c;而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法某特定步骤。 角色&#xff1a; 抽象类&#xff08;AbstractClass&#xff09;&#xff1a;定义抽象的原子操作&#xff08;钩子…

基于开源IM即时通讯框架MobileIMSDK:RainbowChat v9.0版已发布

关于MobileIMSDK MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架&#xff0c;超轻量级、高度提炼&#xff0c;一套API优雅支持UDP 、TCP 、WebSocket 三种协议&#xff0c;支持iOS、Android、H5、标准Java平台&#xff0c;服务端基于Netty编写。 工程开源地址是&am…

HTML5前端开发工程师的岗位职责说明(合集)

HTML5前端开发工程师的岗位职责说明1 职责 1、根据产品设计文档和视觉文件&#xff0c;利用HTML5相关技术开发移动平台的web前端页面; 2、基于HTML5.0标准进行页面制作&#xff0c;编写可复用的用户界面组件; 3、持续的优化前端体验和页面响应速度&#xff0c;并保证兼容性和…

【论文阅读】Feature Inference Attack on Shapley Values

摘要 研究背景 近年来&#xff0c;解释性机器学习逐渐成为一个热门的研究领域。解释性机器学习可以帮助我们理解机器学习模型是如何进行预测的&#xff0c;它可以提高模型的可信度和可解释性。Shapley值是一种解释机器学习模型预测结果的方法&#xff0c;它可以计算每个特征对…

了解Unity编辑器之组件篇Scripts(六)

Scripts&#xff1a;有Unity提供的一些脚本插件&#xff08;自己新建的脚本也会出现在里面&#xff09; 一、TMPro&#xff1a;有一些与文字显示和排版相关的脚本 1.TextContainer&#xff08;文本容器&#xff09;&#xff1a;TextContainer 是一个内容框&#xff0c;用于定…

AIGC人工智能辅助开发:提升效率、优化代码、实现智能编程

文章目录 1. 什么是AIGC人工智能辅助开发&#xff1f;2. AIGC的优势和应用场景2.1 提升开发效率2.2 优化代码质量2.3 实现智能编程 3. 如何用好AIGC人工智能辅助开发&#xff1f;3.1 选择合适的AIGC工具3.2 理解AIGC的工作原理3.3 逐步应用AIGC辅助开发3.4 主动参与AIGC的学习和…