注册

全自动jQuery与渣男的故事

我是个恋旧的人,Github头像还是上古时期端游仙剑奇侠传的截图。



对于前端,如果能jQuery一把梭,我是很开心的。


ReactVue的普及让大家习惯了虚拟DOM的存在。但是虚拟DOM一定是最优解么?


举个例子,要进行如下DOM移动操作:


// 变化前
abcd
// 变化后
dabc

jQuery时调用insertBefored挪到a前面就行。而React基于虚拟DOMDiff会依次对abc执行appendChild,将他们依次挪到最后。


1次DOM操作 vs 3次DOM操作,显然前者更高效。


那么有没有框架能砍掉虚拟DOM,直接对DOM节点执行操作,实现全自动jQuery


有的,这就是最近出的petite-vue


阅读完本文,你会从原理层面了解该框架,如果你还有精力,可以在此基础上深入框架源码。


全自动jQuery的实现


可以将原理概括为一句话:



建立状态更新DOM的方法之间的联系



比如,对于如下DOM


<p v-show="showName">我是卡颂</p>

期望showName状态的变化能影响p的显隐(通过改变diaplay)。


实际是建立showName的变化调用如下方法的联系:


() => {
el.style.display = get() ? initialDisplay : 'none'
}

其中el代表pget()获取showName当前值。


再比如,对于如下DOM


<p v-text="name"></p>

name改变后ptextContent会变为对应值。


实际是建立name的变化调用如下方法的联系:


() => {
el.textContent = toDisplayString(get())
}

所以,整个框架的工作原理呼之欲出:初始化时遍历所有DOM,根据各种v-xx属性建立DOM操作DOM的方法之间的联系。


当改变状态后,会自动调用与其有关的操作DOM的方法,简直就是全自动jQuery



所以,框架的核心在于:如何建立联系?


一个渣男的故事


这部分源码都收敛在@vue/reactivity库中。我并不想带你精读源码,因为这样很没意思,看了还容易忘。


接下来我会通过一个故事为你展示其工作原理,当你了解原理后如果感兴趣可以自己去看源码。



我们的目标是描述:状态变化更新DOM的方法之间的联系。说得再宽泛点,是建立状态副作用之间的联系。


即:状态变化 -> 执行副作用


对于一段关系,可以从当事双方的角度描述,比如:


男生指着女生说:这是我女朋友。


接着女生指着男生说:这是我男朋友。


你作为旁观者,通过双方的描述就知道他们处于一段恋爱关系。


推广到状态副作用,则是:


副作用指着状态说:我依赖这个状态,他变了我就会执行。


状态指着副作用说:我订阅了这个副作用,当我变了后我会通知他。



可以看到,发布订阅其实是对一段关系站在双方视角的阐述



举个例子,如下DOM结构:


<div v-scope="{num: 0}">
<button @click="num++">add 1</button>
<p v-show="num%2">
<span v-text="num"></span>
</p>
</div>

经过petite-vue遍历后的关系图:



框架的交互流程为:




  1. 触发点击事件,状态num变化




  2. 通知其订阅的副作用effect1effect2),执行对应DOM操作




如果从情侣关系角度解读,就是:


num指着effect1说:这是我女朋友。


effect1指着num说:这是我男朋友。


num指着effect2说:这是我女朋友。


effect2指着num说:这是我男朋友。



总结


今天我们学习了一个框架petite-vue,他的底层实现由多段混乱的男女关系组成,上层是一个个直接操作DOM的方法。


不知道看完后你有没有兴趣深入了解下这种关系呢?


感兴趣的话可以看看Vue MasteryVue 3 Reactivity课程。



链接:https://juejin.cn/post/6984710323945078820

0 个评论

要回复文章请先登录注册