当前位置: 首页 > news >正文

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

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.lryc.cn/news/66307.html

相关文章:

  • Rust 快速入门60分① 看完这篇就能写代码了
  • 【5.JS基础-JavaScript的DOM操作】
  • 【大数据之Hadoop】二十九、HDFS存储优化
  • SuperMap GIS基础产品组件GIS FAQ集锦(2)
  • C语言printf()函数中整型格式说明符详解
  • 阿里云服务器地域和可用区怎么选择合适?
  • Java序列化引发的血案
  • 为Linux系统添加一块新硬盘,并扩展根目录容量
  • 树莓派Opencv调用摄像头(Raspberry Pi 11)
  • 国产ChatGPT命名图鉴
  • 操作系统——进程管理
  • 第四十一章 Unity 输入框 (Input Field) UI
  • 10.集合
  • 强化学习p3-策略学习
  • 初学Verilog语言基础笔记整理(实例点灯代码分析)持续更新~
  • 关于 std::condition_variable
  • 可拓展哈希
  • Java 版 spring cloud 工程系统管理 +二次开发 工程项目管理系统源码
  • 通过伴随矩阵怎么求逆矩阵
  • 巡检机器人之仪表识别系统
  • 面试官反感的求职者(下)
  • 可视化绘图技巧100篇分析篇(二)-生存曲线(LM曲线)(补充篇)
  • 【100%通过率 】【华为OD机试python】钟表重合时刻【 2023 Q1考试题 A卷|100分】
  • Java线程池编码示例
  • 如何优化Android 4.x系统设置字体大小
  • Docker安装、Docker基本操作
  • 系统集成项目管理工程师知识点总结
  • 【游戏里的网络同步分析】马里奥制造2 多人模式
  • SSM框架学习-注解开发第三方bean管理
  • 【数据结构与算法】图——邻接表与邻接矩阵