3.0 响应式系统的设计与实现

news2024/11/15 23:18:09

1、Proxy代理对象

Proxy用于对一个普通对象代理,实现对象的拦截和自定义,如拦截其赋值、枚举、函数调用等。里面包含了很多组捕获器(trap),在代理对象执行相应的操作时捕获,然后在内部实现自定义。

const data = {foo: 1}
// 代理data对象
const obj = new Proxy(data, {
  // obj元素赋值触发
  set(target, key, newValue){
    // 赋值自定义
  },
  // 读取obj元素值触发
  get(target, key){
    // 读取时自定义
  }
})

如上代码中obj对象为data对象的代理对象,此时obj内的元素和data一样,当在修改obj内部元素的时候会触发相应的捕获器,这样就可以实现自定义。

那么Proxy代理和响应式系统的设计有什么关系呢?请看以下关于副作用函数的介绍。

2、副作用函数

副作用函数是指会产生副作用的函数, 如:

function effect() {
  document.body.innerText = "hello world"
}

在执行effect函数时会改变body的文本内容,但是如果有其它函数会读取body的文本内容,这时body内容被effect函数修改了,就可以说effect在执行时产生了副作用,即如果一个函数的执行会直接或者间接的影响其他函数的执行就说这个函数产生了副作用

如果此时有这么一段代码:

const obj = {content: "hello world"}
function effect() {
  document.body.innerText = obj.content
}

在执行effect函数的时候会将obj.content的内容显示到body的文本内容中,那么如果我们每次修改obj.content的内容都会触发effect函数的执行,那么是不是就可以说obj.content是 一个响应式数据呢。

修改obj.content的内容然后触发effect函数,是不是使用就上面所述的Proxy代理即可实现,给obj进行代理,在修改content的值时会触发捕获器,此时我们可以在捕获器内自定义功能,就可以调用effect函数。

3、响应式数据的基本实现

接着上文思考,当obj变成了响应式数据会发生什么:

  1. 修改obj.content的值,这会触发effect函数的执行
  2. 触发effect函数,这会获取obj.content的值。

关于第二点触发effect函数一定会获取obj.content的值吗,这其实是肯定的,如果effect函数不会获取obj.content的值那么也就没有绑定的必要了。

使用代码也很容易实现,即:

// 原始对象
const data = {content: "hello world"}

function effect() {
  document.body.innerText = obj.content
}

const obj = new Proxy(data, {
  // 拦截读取操作,此时target为原始对象,key为元素键
  get(target, key) {
    return target[key]
  },
  // 拦截赋值操作
  set(target, key, newVal) {
    target[key] = newVal
    // 设置新值之后执行副作用函数
    effect()
    return true
  }
})

// 修改后触发副作用函数
obj.content = 2

其执行逻辑也很简单,如图所示:

这里主要注意的是当原始对象被代理之后,与副作用函数交互的都是代理对象,而不是原始对象,此时修改原始对象是不会触发副作用函数的。

其实以上的设计并不完善,比如对象内元素的值影响的副作用函数并不止一个,这在开发中很常见,一个数据不一定仅仅绑定一个组件,以上的代码设计就太简单了。其实我们可以设计一个,将对象元素的副作用函数都加入桶中,当这个元素值被修改的时候将桶内的副作用函数全部拿出来执行。

代码如下:

// 用Set来模拟一个桶
const bucket = new Set()

const data = {text: "hello world"}
function effect() {
  document.body.innerText = obj.text
}
const obj = new Proxy(data, {
  // 拦截读取操作,此时target为原始对象,key为元素键
  get(target, key) {
    // 在读取时,将副作用函数装进去
    bucket.add(effect)
    return target[key]
  },
  // 拦截赋值操作
  set(target, key, newVal) {
    target[key] = newVal
    // 设置新的值后取出所有副作用函数并执行
    bucket.forEach(fn => fn())
    return true
  }
})

以上就是一个非常简单且简陋的响应式系统,实现了响应式最基本的功能,但是其实还有非常多的问题都没有解决,如副作用函数是直接使用的effect函数名字获取,但是如果是匿名函数等无法获取,比如这个桶也非常的粗糙,将副作用函数完全塞进去,并没有细分,还有无限递归死循环问题等没有解决,这在之后的内容中会一一解决。

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

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

相关文章

将PDF文件转换为JPG格式图片的3种简单方法

如何在线将PDF文件转换成图片格式?如果您在使用PDF文件时只需要其中一页或几页的内容,将PDF转换为图片可以使您更方便地使用这些内容。下面介绍三种简单易用的PDF转图片的方法。 方法一:记灵在线工具 记灵在线工具是一个免费的在线PDF转换工…

方太也造车?

听说方太也造车了? 造车闹剧层出不穷 近年来,随着智能汽车概念的风行,各大品牌也掀起了一股造车的热潮。一时间,互联网、房地产、家电、手机……各行各业的企业都纷纷粉墨登场,各种造车闹剧层出不穷。 然而很快人们就发…

【三十天精通Vue 3】第二十七天 如何用Vue 3和TensorFlow.js实现人脸识别Web应用?

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3 文章目录 引言一、项目简介1.1 概述1.2 功能特点1.3 技术栈二、准备工作2.1 环境搭建2.2 项目初始化2.3 引入依赖

Bus动态刷新

Bus动态刷新全局广播配置实现 启动 EurekaMain7001ConfigcenterMain3344ConfigclientMain3355ConfigclicntMain3366 运维工程师 修改Gitee上配置文件内容,增加版本号发送POST请求curl -X POST "http://localhost:3344/actuator/bus-refresh" —次发送…

【C++进阶之路】第二篇:多态 抽象类 单继承和多继承关系中的虚函数表

🌟hello,各位读者大大们你们好呀🌟 🍭🍭系列专栏:【C学习与应用】 ✒️✒️本篇内容:多态的概念,多态的构成条件,虚函数重写,C11final和overrid,重…

谈谈我对Edge浏览器分屏功能的使用感受

谈谈我对Edge浏览器分屏功能的使用感受 前言 最近,微软为 Microsoft Edge 浏览器的稳定版本带来了分屏浏览 (Split Screen) 这个新玩意儿,这个功能允许用户在同一个页面以左右视图的形式并排打开两个标签页,类似于软件的分屏。 各位看官如果想…

将经纬度坐标在ArcGIS软件中生成系列矢量数据

目录 环境介绍: 操作内容: 操作步骤: 1、将经纬度坐标值编辑在excel中,注意x、y对应的分别是经度和纬度 2、打开ArcMap软件,加载.xls数据 3、需要选择地理坐标系 4、点矢量数据生成 5、线矢量数据生成 6、面矢量…

2.1 Linux命令行

系列文章目录 第1章 Linux Shell简介 第2章 Shell基础 <本章所在位置> 第3章 Bash Shell基础命令 第4章 Bash Shell命令进阶 第5章 Linux Shell深度理解 第6章 Linux环境变量 第7章 Linux文件权限 第8章 Linux文件系统的管理 第9章 Linux软件安装 第10章 Linux文本编辑器…

Linux多路IO复用:select

1. 多路IO复用 内核监听多个socket文件描述符读写缓冲区属性的变化&#xff0c;若某个文件描述符的读缓冲区有变化&#xff0c;则将该事件告诉应用层。 内核提供多路IO复用的API&#xff1a;select、poll&#xff08;使用较少&#xff09;、epoll。 2. select select原理 用…

设置让Windows每天在指定时间自动关机

其实我们的电脑是可以设置每天在指定的时间点自动关机的&#xff0c;具体操作方法&#xff1a; 1、开打电脑&#xff0c;点击电脑系统左下角windows图标&#xff0c;选择“控制面板”并进入&#xff1b;如图 2、在控制面板界面找到“管理工具”&#xff0c;点击开打&#xff1b…

idea2021.3.x激活教程

第一步: 下载最新的 IDEA 2021.3.3 版本安装包 先从 IDEA 官网下载 IDEA 2021.3.3 版本的安装包&#xff0c;下载链接可以自行百度IDEA官网。 点击下载&#xff0c;耐心等待下载完成。 第二步: 开始安装(已安装可跳过此步骤) 指定安装目录。 勾选创建桌面快捷方式&#xff0…

springboot+java共享厨房租赁信息系统

功能介绍开发环境 springboot是基于spring的快速开发框架, 相比于原生的spring而言, 它通过大量的java config来避免了大量的xml文件, 只需要简单的生成器便能生成一个可以运行的javaweb项目, 是目前最火热的java开发框架 开发语言&#xff1a;Java 框架&#xff1a;springb…

浪潮盒子IPBS9505-多遥控版-S905L/M2芯片-安卓4.4.2-线刷固件包

浪潮盒子IPBS9505-多遥控版-S905L&#xff0f;M2芯片-安卓4.4.2-线刷固件包-内有教程和短接点-当贝纯净桌面。 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&…

微机原理 || 第六章 I/O接口 测试题(答案+解析)

1、下列设备与CPU相连不需要通过接口的是()。 A内存条 B键盘 C U盘. D 硬盘 2、I/O接口电路通常具有()三种端口。 A 数据端口、控制端口、状态端口 (信息分类) 3、以下叙述中&#xff0c;不属于接口功能的是()。 A 提供接口的状态&#xff0c;以便CPU查询 B实现数据格式…

基于vue的毕业生研究生大学生交流学习平台

下面进行系统的功能需求分析。 1.前台功能模块&#xff1a;可以在前台Web浏览器中查看这些功能。 用户注册模块&#xff1a;将用户信息记录到用户表。 用户登录模块&#xff1a;用来区分三种用户&#xff0c;普通用户、普通管理员和超级管理员。 个人信息管理&#xff1a;用户登…

【Linux】Linux安装Maven(图文解说详细版)

文章目录 前言1.去官网下载2.下载完成上传到/opt目录下3.解压缩4.配置环境变量5.刷新配置文件使得配置文件生效6.然后我们运行mvn -v查看是否成功7.出现错误&#xff0c;接下来全程高能带你刨析这个错误&#xff01;8.这里又出现一个坑&#xff0c;就是每次重新进终端的时候mvn…

学习笔记——new关键字在底层究竟做了什么

new关键字&#xff08;操作符&#xff09;在底层究竟做了什么&#xff1f; 一、概念理解 函数调用之前带有关键字new&#xff0c;它就构成了构造函数调用。 与普通函数调用在实参处理、调用上下文、返回值方面不同。 一&#xff09;实参处理 相同点&#xff1a;如果有实参&…

【无标题】每天一道算法练习题--Day24 第一章 --算法专题 --- ----------平衡二叉树专题

力扣关于平衡二叉树的题目还是有一些的&#xff0c;并且都非常经典&#xff0c;推荐大家练习。今天给大家精选了 4 道题&#xff0c;如果你彻底搞明白了这几道题&#xff0c;碰到其他的平衡二叉树的题目应该不至于没有思路。当你领会了我的思路之后&#xff0c; 建议再找几个题…

一文搞懂linux的proc文件

目录 proc文件夹是干嘛用&#xff1f; proc下都有什么系统信息? /proc/bus /proc/buddyinfo /proc/cgroups /proc/cmdline /proc/consoles /proc/cpuinfo /proc/crypto /proc/devices /proc/diskstats /proc/execdomains /proc/fb /proc/filesystems …

JVM 体系结构

JVM: 跨平台语言 需要不同语言由自己编译器&#xff0c;生成符合 JSR-292 JVM规范的字节码文件&#xff0c;即可在 Java 虚拟机中运行 多语言混合编程: Java 平台上的多语言混合编程正成为主流&#xff0c;通过特定领域的语言去解决特定领域的问题是当前软件开发应对日趋复杂…