手写vuex

news2024/9/28 19:15:46

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.state
    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)
}

模块划分*

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.coloradmin.cn/o/808637.html

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

相关文章

详解Mybatis之逆向工程问题

编译软件:IntelliJ IDEA 2019.2.4 x64 操作系统:win10 x64 位 家庭版 Maven版本:apache-maven-3.6.3 Mybatis版本:3.5.6 文章目录 一. Mybatis中的逆向工程是什么?二. 什么是MBG?三. MBG如何使用&#xff1…

Android Studio 启用设备远程调试配置完整步聚

启用手机设置->开发者选项-无线调试,然后选择允许 已启用后无线调试变成绿色 ,点击无线调试进入详情页面 点击Android Studio的Device Manager 下的WIFI图标 会弹出下图窗口 打开手机的开发者选项中的WIFI调试(无线调试)下的使用二维码配对设备进行扫描. 设备配对成功后手机…

JDBC Common Connection Problems

连接问题 Access denied for user ‘root’‘localhost’ (using password: YES) 第一种情况 问题描述 环境:IDEA 2021.1 windows11 mysql8.0 已知条件:1.已正常安装数据库2.无法通过CMD输入mysql -u root -p 密码进入数据库3.无法通过Navicat进入4…

2023-07-29:给你一个由数字组成的字符串 s,返回 s 中独特子字符串数量。 其中的每一个数字出现的频率都相同。

2023-07-29:给你一个由数字组成的字符串 s,返回 s 中独特子字符串数量。 其中的每一个数字出现的频率都相同。 答案2023-07-29: 大体步骤如下: 1.初始化变量base为固定值1000000007,用于计算哈希码。 2.创建一个空…

InnoDB引擎底层逻辑讲解——架构之内存架构

1.InnoDB引擎架构 下图为InnoDB架构图,左侧为内存结构,右侧为磁盘结构。 2.InnoDB内存架构讲解 2.1 Buffer Pool缓冲池 2.2 Change Buffer更改缓冲区 2.3 Adaptive Hash Index自适应hash索引 查看自适应hash索引是否开启: show variable…

qt截图软件中画箭头代码原理

截图工具中,需要画一个指向箭头, 该箭头的形状解析示意图如下所示, 对应的qt代码如下: // 画出一个箭头线,主要是算出这几个点。 // 这个箭头形状是这样的,胖嘟嘟的那种,但是出发点是一个细的 Q…

机器学习深度学习——权重衰减

👨‍🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——模型选择、欠拟合和过拟合 📚订阅专栏:机器学习&&深度学习 希望文章对你…

教雅川学缠论04-笔

笔由3部分组成: 顶分型K线底分型,或者 底分型K线顶分型 注意:笔加一起至少7根K线,因为一个底分型至少3根,K先至少1个,顶分型至少3根 下图中红色线段就是一个标准的笔,它始于一个底分型&#xff…

❤️创意网页:创建更炫酷的动态网页——彩色数字(1到9)粒子动画

✨博主:命运之光 🌸专栏:Python星辰秘典 🐳专栏:web开发(简单好用又好看) ❤️专栏:Java经典程序设计 ☀️博主的其他文章:点击进入博主的主页 前言:欢迎踏入…

基于WSL2、Ubuntu和VS Code的CUDA平台运行C语言程序

一、CUDA程序执行方法 执行步骤为: 安装Visual Studio Code。在Visual Studio Code中安装插件WSL与电脑的WSL2进行连接。点击左下角,然后再选择连接到WSL。 在WSL中创建以 .cu 为后缀的文件。 rootDESKTOP-HR6VO5J:~# mkdir CUDA /…

VMware Linux 可视化增加磁盘

1、VMware 增加磁盘 2、disks挂载磁盘 此处我挂载的是20G磁盘,截图只是用5G的做过程演示例子。 3、验证挂载磁盘

Chrome 浏览器+Postman还能这样做接口测试 ?

如果把测试简单分为两类,那么就是客户端测试和服务端测试。客户端的测试包括UI测试,兼容性测试等,服务端测试包括接口测试。接口测试检查数据的交换,传递和控制管理过程,它绕过了客户端,直接对服务端进行测…

UE5 C++ SplineMesh蓝图函数库实现(小白笔记)

UE5 C++ SplineMesh的蓝图函数库实现方法 UAAABlueprintFunctionLibrary UAAABlueprintFunctionLibrary.h // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "Components/Spl…

【Java开发】 Mybatis-Flex 01:快速入门

Mybatis 作为头部的 ORM 框架,他的增强工具可谓层出不穷,比如出名的 Mybatis-Plus 和 阿里云开源的 Fluent-MyBatis,如今出了一款 Mybatis-Flex ,相比前两款功能更为强大、性能更为强悍,不妨来了解一下。 目录 1 Myba…

CAD Voronoi3D V1.0.1 版本更新说明

更新说明 CAD Voronoi3D V1.0.1版本对泰森多边形晶格进行进一步的优化。 采用新算法大幅度减少形体边界出现小晶格的可能性,使区块更均匀: 优化曲边边界晶格曲率问题,消除曲边形体晶格边界曲率过大现象: 优化生成算法&#xff…

Ubuntu—vi编辑器的使用一

vi编辑器 vi是Linux中最基本的编辑器。但vi编辑器在系统管理、服务器配置工作中永远都是无可替代的。 vi编辑器的使用 vi有以下三种模式 命令行模式 用户在用vi编辑文件时, 最初进入的是该模式。可以进行复制、粘贴等操作 插入模式 进行文件编辑, 按…

35.图片幻灯片

图片幻灯片 html部分 <div class"carousel"><div class"image-container"><img src"./static/20180529205331_yhGyf.jpeg" alt"" srcset""><img src"./static/20190214214253_hsjqw.webp"…

PP-Matting: AI高精度图像前景Matting,让抠图轻而易举

分割和Matting的一个重要区别是:分割返回的是像素分类标签,其结果是整型数据;而Matting返回的是属于前景或背景的概率P,从而在前景与背景交互区域产生渐变的效果,使得抠图更加自然。Matting分割模型训练完成后,对于原始图像每个位置上的像素,都将生成一个表示其前景透明…

AB 压力测试

服务器配置 阿里云Ubuntu 64位 CPU1 核 内存2 GB 公网带宽1 Mbps ab -c100 -n1000 http://127.0.0.1:9501/ -n&#xff1a;在测试会话中所执行的请求个数。默认时&#xff0c;仅执行一个请求。 -c&#xff1a;一次产生的请求个数。默认是一次一个。 ab -c 100 -n 200 ht…

阿里云SMS测试三步曲

文章目录 阿里云SMS测试三步曲申请签名与模板申请签名申请模板 AcesssKey测试用例Apache Maven测试代码 阿里云SMS测试三步曲 申请签名与模板 签名与模板的申请的审核时间有1个多小时&#xff0c;且是9~21点时间段内 申请签名和模板时如果是为了做测试&#xff0c;要特别说明…