加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 站长资讯 > 动态 > 正文

突破Hooks所有限制,只需50行代码

发布时间:2021-11-08 00:59:06 所属栏目:动态 来源:互联网
导读:大家好,我是卡颂。 你是否很讨厌调用顺序的限制(不能写在条件语句里)? 你是否遇到过在中使用了某个,又忘记将其加入,导致回调执行时机出问题? 怪自己粗心?怪自己不好好看文档? 答应我,不要怪自己。 根本原因在于没有将实现为响应式更新。 是实现难
大家好,我是卡颂。
 
你是否很讨厌调用顺序的限制(不能写在条件语句里)?
 
你是否遇到过在中使用了某个,又忘记将其加入,导致回调执行时机出问题?
 
怪自己粗心?怪自己不好好看文档?
 
答应我,不要怪自己。
 
根本原因在于没有将实现为响应式更新。
 
是实现难度很高么?本文会用50行代码实现无限制版,其中涉及的知识也是、等基于响应式更新的库的底层原理。
 
本文的正确食用方式是收藏后用电脑看,跟着我一起敲代码(完整在线链接见文章结尾)。
 
手机党要是看了懵逼的话不要自责,是你食用方式不对。
 
注:本文代码来自Ryan Carniato的文章Building a Reactive Library from Scratch,老哥是作者
 
万丈高楼平地起
 
首先来实现:
 
返回值数组第一项负责取值,第二项负责赋值。相比,我们有个小改动:返回值的第一个参数是个函数而不是本身。
 
使用方式如下:
 
没有黑魔法
 
接下来实现,包括几个要点:
 
依赖的改变,回调执行
 
不需要显式的指定依赖项(即中的第二个参数)
 
举个例子:
 
变化后第一个会执行回调(因为他内部依赖),但是第二个不会执行。
 
前端没有黑魔法,这里是如何实现的呢?
 
答案是:订阅发布。
 
 
继续用上面的例子来解释订阅发布关系建立的时机:
 
当定义后他的回调会立刻执行一次,在其内部会执行:
 
执行时会建立与之间订阅发布的关系。
 
当下次执行(setter)时会通知订阅了变化的,执行其回调函数。
 
数据结构之间的关系如图:
 
 
每个内部有个集合,用来保存订阅该state变化的。
 
是每个对应的数据结构:
 
其中:
 
:该的回调函数
 
:该依赖的对应的集合
 
我知道你有点晕。看看上面的结构图,缓缓,咱再继续。
 
实现useEffect
 
首先需要一个栈来保存当前正在执行的。这样当调用时才知道应该与哪个建立联系。
 
举个例子:
 
执行时需要知道自己处在的上下文中(而不是),这样才能与建立联系。
 
接下来实现,包括如下功能点:
 
每次回调执行前重置依赖(回调内部的会重建依赖关系)
 
回调执行时确保当前处在栈顶
 
回调执行后将当前从栈顶弹出
 
代码如下:
 
用来移除该与所有他依赖的之间的联系,包括:
 
订阅关系:将该订阅的所有变化移除
 
依赖关系:将该依赖的所有移除
 
移除后,执行回调会再逐一重建关系。
 
改造useState
 
接下来改造,完成建立订阅发布关系的逻辑,要点如下:
 
调用时获取当前上下文的,建立关系
 
调用时通知所有订阅该变化的回调执行
 
的实现,同样包括2个关系的建立:
 
让我们来试验下:
 
实现useMemo
 
接下来基于已有的2个实现:
 
自动依赖跟踪
 
这套50行的还有个强大的隐藏特性:自动依赖跟踪。
 
我们拓展下上面的例子:
 
现在我们有3个:、、。
 
作为,依赖以上三个。
 
最后,当变化时,会触发回调。
 
当以上代码运行后,基于初始的3个,会计算出,进而触发回调,打印:
 
接下来调用:
 
下面的事情就有趣了,当调用:
 
并没有打印。
 
这是因为当导致为后,进入如下逻辑:
 
由于没有执行,所以与已经没有订阅发布关系了!
 
只有当后,进入如下逻辑:
 
此时才会重新依赖与。
 
自动的依赖跟踪,是不是很酷~
 
总结
 
至此,基于订阅发布,我们实现了可以自动依赖跟踪的无限制。
 
这套理念是最近几年才有人使用么?
 
早在2010年初就用这种细粒度的方式实现响应式更新了。
 
不知道那时候,Steve Sanderson(作者)有没有预见到10年后的今天,细粒度更新会在各种库和框架中被广泛使用。

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读