简单自定义vuex的设计思路

vuex集中式存储管理应用所有组件的状态,并以响应的规则保证状态以可预测的方式 发生变化。

步骤:

1.Store类,保存选项,_mutations,_actions,getters

2.响应式状态:new Vue方式设置响应式。

3.get state 和 set state commit dispatch

4.install方法 挂载store到vue的原型对象上,所有实例都可以读取到。

生成Vuex类

说到底,vuex也还是个插件,所以生成一个类,按照使用插件的形式将其export导出。

挂载到Vue实例上我们还是使用mixin的方式,原理和vue-router的自定义方式一致,这里就不多说了。

let Vueclass Store{constructor(options){//保存选项// state为响应式数据this.state = new Vue({data:options.state})}
}function install(_Vue){Vue = _Vue//挂载$store给外面使用Vue.mixin({beforeCreate() {if(this.$options.store){//挂载到vue原型上,每个vue实例都可以访问到Vue.prototype.$store = this.$options.store}},})
}export default {Store,install
}

但是在这里,我们使用new Vue的data属性来让state成为一个响应式的数据,有个弊端就是能够直接的修改data里的数据,那这样违反了vuex单向数据流的特点,那么我们要封装一下。

官网解释,有两个的$变量就不做代理,所以也就不会再_vm的根上访问到$$state这个属性,同时设置set get俩属性,get为只读,那么外面就无法修改state的值,只能通过commit或actions进行修改。_vm下的响应式对象会挂载在_data的对象上,_vm下的$data是一个原始对象,不具备响应式,所以使用_data。

如下图,$data不存在observer

class Store{constructor(options){//保存选项// state为响应式数据this._vm = new Vue({data:{$$state:options.state}})}//给用户暴露接口get state(){console.log(this._vm);return this._vm._data.$$state}set state(val){throw Error('replaceSate')}
}

commit和dispatch

响应式的数据发生变化就会引起render函数渲染数据 ,在commit中会接收到参数,我们在构造函数中存储传入的mutations和actions,然后在commit和dispach中匹配到详情的操作,然后执行。

但是在执行过程中有坑,this的指向问题:当前的调用是在外部,所以指向的是外部的store实例,是没有commit等参数,所以没有办法调用到。需要在constructor存储上下文,并且改变this指向到当前的实例,获取到对应的上下文即可。

class Store{constructor(options){//保存选项this._mutations  = options.mutations||{}this._actions  = options.actions||{}// state为响应式数据this._vm = new Vue({data:{$$state:options.state}})//上下文的绑定this.commit=this.commit.bind(this)this.dispatch=this.dispatch.bind(this)}//给用户暴露接口get state(){return this._vm._data.$$state}set state(val){throw Error('replaceSate')}//store.commit(type,payload)commit(type,payload){//获取mutitionsconst entry = this._mutations[type]if(!entry){console.error('unknown mutition type');}entry(this.state,payload)}dispatch(type,payload){const entry = this._actions[type]if(!entry){console.error('unknown actions type');}console.log(this);entry(this,payload)//注意这里的this指向问题,当前的调用是在外部,所以指向的是外部的store实例,是没有commit等参数,所以没有办法调用到。需要在constructor存储上下文,并且改变this指向。}
}

getters

getters我们可以借助computed属性,只可获取不可更改,获取到getters的key给到computed,并且在给一个函数,在其内部调用fn并且传入state,再将computed属性进行响应式处理。

this._wrappedGetters  = options.getters||{}//定义computed选项const computed={}this.getters={}const store= thisObject.keys(this._wrappedGetters).forEach(key=>{//获取用户定义的getterconst fn = store._wrappedGetters[key]// 转换为computed可以使用的无参数形式computed[key]=function(){return fn(store.state)}//为getters定义只读属性Object.defineProperty(store.getters,key,{get:()=>{return store._vm[key]}})})// state为响应式数据this._vm = new Vue({data:{$$state:options.state},computed})

附完整代码:

let Vueclass Store{constructor(options){//保存选项this._mutations  = options.mutations||{}this._actions  = options.actions||{}this._wrappedGetters  = options.getters||{}//定义computed选项const computed={}this.getters={}const store= thisObject.keys(this._wrappedGetters).forEach(key=>{//获取用户定义的getterconst fn = store._wrappedGetters[key]// 转换为computed可以使用的无参数形式computed[key]=function(){return fn(store.state)}//为getters定义只读属性Object.defineProperty(store.getters,key,{get:()=>{return store._vm[key]}})})// state为响应式数据this._vm = new Vue({data:{$$state:options.state},computed})//上下文的绑定this.commit=this.commit.bind(this)this.dispatch=this.dispatch.bind(this)}//给用户暴露接口get state(){return this._vm._data.$$state}set state(val){throw Error('replaceSate')}//store.commit(type,payload)commit(type,payload){//获取mutitionsconst entry = this._mutations[type]if(!entry){console.error('unknown mutition type');}entry(this.state,payload)}dispatch(type,payload){const entry = this._actions[type]if(!entry){console.error('unknown actions type');}entry(this,payload)//注意这里的this指向问题,当前的调用是在外部,所以指向的是外部的store实例,是没有commit等参数,所以没有办法调用到。需要在constructor存储上下文,并且改变this指向。}
}function install(_Vue){Vue = _Vue//挂载$store给外面使用Vue.mixin({beforeCreate() {if(this.$options.store){//挂载到vue原型上,每个vue实例都可以访问到Vue.prototype.$store = this.$options.store}},})
}export default {Store,install
}

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

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

相关文章

使用Java8的Stream流的Collectors.toMap来生成Map结构

问题描述 在日常开发中总会有这样的代码,将一个List转为Map集合,使用其中的某个属性为key,某个属性为value。 常规实现 public class CollectorsToMapDemo {DataNoArgsConstructorAllArgsConstructorpublic static class Student {private…

OpenCV-python numpy和基本作图

文章目录 一、实验目的二、实验内容三、实验过程Numpy1.NumPy 操作2.NumPy Ndarray 对象3.NumPy 基本类型4.NumPy 数组属性ndarray.ndimndarray.shapendarray.itemsizendarray.flags 5.NumPy 创建数组numpy.emptynumpy.zerosnumpy.ones 6.NumPy 从已有的数组创建数组numpy.asar…

SpringDataRedis 操作 Redis,并指定数据序列化器

文章目录 1. SpringDataRedis 概述2. 快速入门2.1 导入pom坐标2.2 配置文件2.3 测试代码2.4 数据序列化器2.5 StringRedisTemplate2.6 总结 1. SpringDataRedis 概述 SpringData 是Spring 中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模…

使用vue UI安装路由插件

1.使用vue创建项目 vue create vue-appvue ui 2.使用vue ui界面创建管理项目 终端页面输入:vue ui 创建项目 安装完成。可以直接在ui界面运行,也可以在编辑器中使用命令运行 安装路由,安装状态 选择插件 - 添加vue-router、添加vuex 安装…

C# WebSocket简单使用

文章目录 前言Fleck调试工具初始化简单使用 前言 最近接到了一个需求,需要网页实现上位机的功能。那就对数据传输的实时性要求很高。那就只能用WebSocket了。这里简单说一下我的WebSocket如何搭建 Fleck C# WebSocket(Fleck) 客户端:html Winfrom Fleck Github官网…

Unity3D中实现箭头指向目标点的效果(shader)

系列文章目录 Unity工具 文章目录 系列文章目录前言一、效果如下二、制作步骤2-1、制作shader2-2、shader代码2-3、制作材质球2-4、新建Quad2-5、制作预制体2-6 、实现代码2-7、设置Quad到脚本2-8、路径设置如下 三、说明四、运行程序总结 前言 大家好,我是心疼你…

鸿蒙开发—UI框架概述

基本概念 UI框架 HarmonyOS提供了一套UI开发框架,即方舟开发框架(ArkUI框架)。方舟开发框架可为开发者提供应用UI开发所必需的能力,比如多种组件、布局计算、动画能力、UI交互、绘制等。 方舟开发框架针对不同目的和技术背景的…

数据结构与算法编程题47

无向图的邻接表 #include <iostream> using namespace std;#define MVnum 100 typedef string VertexType;typedef struct ArcNode {int adjvex;struct ArcNode* nextarc;int weight; }ArcNode;typedef struct VNode {VertexType data;struct ArcNode* firstarc; }VNode,…

性能测试工具:Jmeter介绍

JMeter是一个开源的Java应用程序&#xff0c;由Apache软件基金会开发和维护&#xff0c;可用于性能测试、压力测试、接口测试等。 1. 原理 JMeter的基本原理是模拟多用户并发访问应用程序&#xff0c;通过发送HTTP请求或其他协议请求&#xff0c;并测量响应时间、吞吐量、并发…

关于对Spring事件监听机制相关解析

1、Spring事件监听器使用 Spring事件监听体系包括三个组件&#xff1a;事件、事件监听器&#xff0c;事件广播器 事件&#xff1a;定义事件类型和事件源&#xff0c;需要继承ApplicationEvent import org.springframework.context.ApplicationEvent; public class OrderEvent…

虹科新闻丨虹科正式加入广州市新联会科创分会

来源&#xff1a;虹科电子科技有限公司 虹科新闻丨虹科正式加入广州市新联会科创分会 11月7日&#xff0c;由广州市委统战部、广州开发区管委会、黄埔区人民政府指导&#xff0c;佳都集团、佳都科技集团、广州开发区投资集团共同主办的未来之城大湾区元宇宙创新示范中心&#…

金鸣表格文字识别大师扫描仪使用技巧

所需硬件&#xff1a;PC&#xff08;电脑&#xff09;、扫描仪 所需软件&#xff1a;金鸣表格文字识别大师5.0以上版本&#xff08;以下简称“本软件”&#xff09; 实现功能&#xff1a;直接用扫描仪扫描图片并将其转换为可编辑的excel或word. 实现原理&#xff1a;本软件利…

DevEco Studio集成ArkUI-X

语雀知识库地址&#xff1a;语雀HarmonyOS知识库 飞书知识库地址&#xff1a;飞书HarmonyOS知识库 在上篇文章(HarmonyOS应用开发工具DevEco Studio安装与使用)中我说到官方推出了4.0 Beta版本的IDE&#xff0c;这篇文章就来介绍这个版本的安装与使用 该版本集成了HarmonyOS多…

利用ChatGPT的写作能力,可以更好地组织思路、提升论文的逻辑性和质量

2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车…

UE4.27-UE5.1设置打包Android环境

打包Android配置文件 1. 配置打包Android的SDK需求文件位于下面文件中&#xff1a; 2. 指定了对应的SDK环境变量名字以及NDK需求等&#xff1a; UE4.27-UE5.1--脚本自动配置 安装前提 1. 务必关闭虚幻编辑器和Epic Games Launcher&#xff0c;以确保NDK组件的安装或引擎环境…

P1005 [NOIP2007 提高组] 矩阵取数游戏

网址&#xff1a;P1005 [NOIP2007 提高组] 矩阵取数游戏 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 动态规划和高精度的组合&#xff0c;使我的滨州旋转 最后只得了80&#xff0c;两个测试点超时了 看题解有人是用了int128来做的&#xff0c;明天学一下 我的递归思路和…

关于 mapboxgl 的常用方法及效果

给地图标记点 实现效果 /*** 在地图上添加标记点* point: [lng, lat]* color: #83f7a0*/addMarkerOnMap(point, color #83f7a0) {const marker new mapboxgl.Marker({draggable: false,color: color,}).setLngLat(point).addTo(this.map);this.markersList.push(marker);},…

AI必然成为未来的OS

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 ChatGPT引入插件&#xff0c;AI必然成为未来OS&#xff0c;或至少成为绝大多数APP首选入口。未来软件开发根据任务不同&#xff0c;有两种不同范式&#xff1a; &a…

unity 2d 入门 飞翔小鸟 场景淡入淡出功能(三)

1、在图层新建个空的图层 场景2 2创建c#脚本 脚本创建好后&#xff0c;将脚本推拽进空白图层里面&#xff0c;将黑色图片拉进去脚本的参数里面&#xff0c;如上面最后一张图&#xff0c;两个切换的场景都要进行上述操作 using System.Collections; using System.Collection…

识别低效io引起的free buffer waits

产生事发时间段的awr报告 Top 5 wait events 这里重点关注&#xff1a; 1.free buffer waits 2.enq_HW-contention 3.enq:tx-row lock contention enq:HW-contention属于水位线的争用&#xff0c;已经透过alter table allocate extent&#xff0c;提前分配空间,这里不做讨论 …