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