响应式编程-数据劫持

响应式编程的核心思想是观察者模式,被观察的对象我们可以称之为数据源,所以,数据是响应式编程所关注的核心。

假设有一个数据对象,有一个字段age值为18:

let obj = {age:18
}

然后有一个函数,在这个函数打印age字段:

function fn(){console.log(obj.age);
}fn();//18

现在我们想当我们修改age字段值时,fn函数能够自动执行。

那要怎么实现呢?

有这样一种思路是:当age字段被读取的时候,我们记住是什么函数读取了它;在给age字段设值的时候,我们拿出记录的函数并调用它。这样我们每次修改age的时候就会自动执行相关函数了。

下面我们按这种思路具体实现一下:

首先,这里面涉及到三个角色:1、数据对象  2、数据字段  3、副作用函数(在函数内部修改了函数外部的数据),它们的关系如下:

对象|__字段1|  |__副作用函数1||__字段2|__副作用函数1|__副作用函数2

然后,我们需要对obj数据对象字段的读取和写入操作进行劫持以达到我们记录和调用副作用函数的目的,这里我们通过js中的Proxy来代理obj对象的get和set属性。

我们先来看一下简单版代码,只有一个副作用函数,一个数据对象,一个字段:

// 数据对象
const data = { age:18
};const obj = new Proxy(data, {// 拦截读取操作get(target, key) {return target[key]},// 拦截设置操作set(target, key, newVal) {target[key] = newValfn();}
})// 副作用函数
function fn(){console.log(obj.age);
}fn();setTimeout(()=>{obj.age = 20;
},2000)

最后来一个支持多对象,多字段,多副作用函数的vue源码简化版本:

// 当前副作用函数
let activeEffect;
// 存储副作用函数的桶 
const bucket = new WeakMap()
const data = { text: 'hello world' 
};const obj = new Proxy(data, {// 拦截读取操作get(target, key) {// 将副作用函数 activeEffect 添加到存储副作用函数的桶中track(target, key)// 返回属性值return target[key]},// 拦截设置操作set(target, key, newVal) {// 设置属性值target[key] = newVal// 把副作用函数从桶里取出并执行trigger(target, key)}
})// 在 get 拦截函数内调用 track 函数追踪变化
function track(target, key) {// 没有 activeEffect,直接 returnif (!activeEffect) returnlet depsMap = bucket.get(target)if (!depsMap) {bucket.set(target, (depsMap = new Map()))}let deps = depsMap.get(key)if (!deps) {depsMap.set(key, (deps = new Set()))}deps.add(activeEffect)
}// 在 set 拦截函数内调用 trigger 函数触发变化
function trigger(target, key) {const depsMap = bucket.get(target)if (!depsMap) returnconst effects = depsMap.get(key)effects && effects.forEach(fn => fn())
}// 注册并执行副作用函数
function effect(fn){activeEffect = fn;fn && fn();
}// 注册并执行一个副作用函数
effect(() => {console.log(obj.text)
})effect(() => {console.log(obj.text+'第二个副作用函数')
})// 执行
setTimeout(() => {obj.text = 'hello vue boy'
}, 2000)

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

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

相关文章

quota使用

一、检查系统是否支持 grep CONFIG_QUOTA /boot/config* CONFIG_QUOTAy CONFIG_QUOTA_NETLINK_INTERFACEy # CONFIG_QUOTA_DEBUG is not set CONFIG_QUOTA_TREEy CONFIG_QUOTACTLy CONFIG_QUOTACTL_COMPATy二、安装 yum install -y quota三、配置 3.1 创建磁盘 格式一定要 …

【RPC注册发现框架实战】一个简易的RPC注册发现框架

Java实现 服务端起10个线程ID监听40-49这10个端口,这10个端口注册到注册中心,提供同一个服务,发个A,响应B,客户端起10个线程去注册中心请求 好的,我们可以通过实现一个简单的服务端、注册中心和客户端来达到…

【机器学习】精准农业新纪元:机器学习引领的作物管理革命

📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀目录 🔍1. 引言📒2. 精准农业的背景与现状🍁精准农业的概念与发展历程🍂国内外精准农业实践案…

002-ESP32怎么 上电就能启动指定代码

ESP32在上电后能够启动指定代码,主要依赖于其内部的启动流程和固件配置。以下是一个详细的步骤说明,以及如何实现这一功能: 一、ESP32的启动流程 ESP32的启动流程大致可以分为以下几个阶段: 一级引导程序:被固化在ES…

【数据结构】手写堆 HEAP

heap【堆】掌握 手写上浮、下沉、建堆函数 对一组数进行堆排序 直接使用接口函数heapq 什么是堆???堆是一个二叉树。也就是有两个叉。下面是一个大根堆: 大根堆的每一个根节点比他的子节点都大 有大根堆就有小根堆&#xff1…

Qt/QML学习-BusyIndicator

QML学习 BusyIndicator例程视频讲解代码 main.qml import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15Window {width: 640height: 480visible: truetitle: qsTr("Hello World")BusyIndicator {id: busyIndicatoranchors.fill: parentM…

深入解析std::string的设计哲学【C++、STL库】

为什么在C中字符串长度需要调用函数而不是直接访问?深入解析std::string的设计哲学 在C中,获取字符串长度需要调用size()或length()方法,而不是直接访问一个常量或属性。这一设计让许多初学者感到困惑。那么,为什么C会选择这种方…

(南京观海微电子)——二极管应用及选取

二极管是 用半导体材料(硅、硒、锗等)制成的一种电子器件。二极管有两个电极,正极,又叫阳极;负极,又叫阴极,给二极管两极间加上正向电压时,二极管导通, 加上反向电压时,二极管截止。…

Vue1-Vue核心

目录 Vue简介 官网 介绍与描述 Vue的特点 与其它 JS 框架的关联 Vue周边库 初识Vue Vue模板语法 数据绑定 el与data的两种写法 MVVM模型 数据代理 回顾Object.defineProperty方法 何为数据代理 Vue中的数据代理 数据代理图示 事件处理 事件的基本使用 事件修…

【“码上”大模型简介】

“码上”大模型 码上是北京邮电大学EZCoding雏雁/大创团队自主研发、运营和支撑的大模型赋能的智能编程教学应用平台。针对编程教学过程中学生亟需一对一辅导的需求痛点,码上基于讯飞星火大模型,采用北邮自研核心技术,为学生提供实时、个性化…

【UE5.1】Chaos物理系统基础——06 子弹破坏石块

前言 在前面我们已经完成了场系统的制作(【UE5.1】Chaos物理系统基础——02 场系统的应用_ue5)以及子弹的制作(【UE5.1 角色练习】16-枪械射击——瞄准),现在我们准备实现的效果是,角色发射子弹来破坏石柱。…

前端代码基本逻辑-vue3

前端vue建立过程 安装nodejs 官网下载安装,并且记住安装路径,记得配置系统变量Path 安装VUE/CLI npm install -g vue/cli --全局安装vue 使用VUE/CLI生成代码框架 vue create your-project-name --我的your-project-name为web 运行项目 cd your-…

STM32智能空气质量监测系统教程

目录 引言环境准备智能空气质量监测系统基础代码实现:实现智能空气质量监测系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景:空气质量监测与优化问题解决方案与优化收尾与总结 1. 引言 智能空…

基于Java+SpringMvc+Vue技术的药品进销存仓库管理系统设计与实现系统(源码+LW+部署讲解)

注:每个学校每个老师对论文的格式要求不一样,故本论文只供参考,本论文页数达到60页以上,字数在6000及以上。 基于JavaSpringMvcVue技术的在线学习交流平台设计与实现 目录 第一章 绪论 1.1 研究背景 1.2 研究现状 1.3 研究内容…

卸载wps office的几种方法收录

​ 第一种方法: 1.打开【任务管理器】,找到相关程序,点击【结束任务】。任务管理器可以通过左下角搜索找到。 2.点击【开始】-【设置】-【应用】-下拉找到WPS应用,右键卸载,不保留软件配置 …

SQLite3封装类教程

SQLite3封装类教程 SQLite是一种轻量级的数据库,它不需要一个独立的服务器进程。SQLite数据库存储在一个单一的磁盘文件中,这使得它非常适合小型到中型的应用程序,例如移动应用、桌面应用和小型的Web应用。以下是使用Python封装SQLite3数据库…

Promise.all、any、race和allSettled的相同点与不同点与应用场景

在JavaScript中,Promise对象是一种处理异步操作的方式。它允许我们以一种更优雅的方式来处理异步代码,而不是使用回调函数。在Promise中,有一些方法可以帮助我们更好地管理多个Promise实例,这些方法包括Promise.all、Promise.any、…

tomcat为什么要自定义类加载器?

一个Tomcat中可以部署多个应用,而每个应用中都存在很多类,并且各个应用中的类是独立的,全类名是可以相同的。 比如一个订单系统中可能存在com.xushu.User类,一个库存系统中可能也存com.xushu.User类,一个Tomcat&#x…

Git学习1_Git安装(CSDN_20240714)

git下载 git下载官网如下: Git - Downloads (git-scm.com)https://git-scm.com/downloads 根据机器操作系统,下载对应的安装包 git安装 1. 点击安装程序,进入安装界面,如下图所示,点击next。 2. 选择安装路径&…

【laravel+Easyswoole】

使用 Laravel 和 Easyswoole 进行项目开发。 1. 环境准备 确保你的开发环境满足以下要求: PHP > 7.4ComposerGit安装并启用 Swoole 扩展(可以通过 pecl install swoole 安装,然后添加 extensionswoole.so 到 php.ini) 2. 创…