大家好,我是卡颂。
周末没啥事,筹备找个优良且代码量不多的库学习下。最终抉择了最近公布的 petite-vue,起因如下:
- 代码量少(只有 5.8kb),且源码模块化水平高(相比于
React
),易读 - 基于
Vite
构建,执行yarn dev
就能开始调试源码 - 没有
虚构 DOM
、编译时计划,能够作为读Vue
源码的铺垫 - 底层的响应式更新原理同样实用于
Mobx
、SolidJS
等库,一次浏览多份播种
就决定是他了。
然而周末工夫这么贵重,而且我都 4 年没用过 Vue
了,如何能力高效学习源码呢?
最好是 在不看源码的状况下把源码学了。
接下来,我以 petite-vue
为例为大家示范学源码的正确姿态。
怎么快怎么来
能够将 petite-vue
了解为:用实在 DOM
取代 Vue
模版的繁难Vue
。
比方如下Demo
:
<script type="module">
import {createApp} from '../src'
createApp({count: 0}).mount()
</script>
<div v-scope>
<button @click="count++">add 1</button>
<p>{{count}}</p>
</div>
div
及其子孙节点是实在的 DOM
标签,所以页面初始化时如下:
接着执行如下代码,实现 petite-vue
初始化:
createApp({count: 0}).mount()
此时页面:
读框架源码切忌一上手就从入口函数一路调试,很容易就懵逼了。正确的形式是像剥洋葱一样一层一层剥开:
所以,让咱们先从 Performance
面板看看 首屏渲染 的调用栈:
调用栈大体分为蓝框、红框两局部,先看右边蓝框局部:
通过 createContext
与reactive
关键词判断大略是创立 响应式上下文
。至于 响应式
的含意,咱们还不分明。
接着看左边红框局部:
从调用栈深度、页面渲染的成果咱们猜想,这部分做的工作包含:
- 遍历
DOM
- 实现数据与视图的双向绑定
- 初始化渲染
接下来,咱们来验证猜测。
留神,到目前为止,咱们一行源码都还没看
验证遍历 DOM
调用栈中 walk
与walkChildren
被调用屡次,大概率他们就是具体遍历工作执行的办法,让咱们确认下。
在源码 walk
办法中打上log
:
export const walk = (node: Node, ctx: Context): ChildNode | null | void => {console.log('walk', node);
// ...
}
排除换行符 "\n"
对应的文本节点,打印程序如下:
walk div
walk <button>add 1</button>
walk "add 1"
walk <p>0</p>
walk "0"
从打印后果看,这是个 深度优先遍历(如果有子节点就遍历子节点,没有子节点就遍历兄弟节点)
显然,petite-vue
mount
时采纳 深度优先遍历 ,并对遍历到的每个与 上下文状态 相干的 DOM
节点进行解决。
在 Demo
中,上下文蕴含状态{count: 0}
:
createApp({count: 0}).mount()
在遍历后 <p>{{count}}</p>
变为<p>0</p>
。
确定双向绑定的粒度
接下来咱们须要确认双向绑定的作用范畴,即:
触发更新后,多大范畴的
DOM
会被从新遍历并执行相应DOM
操作?
关上 Performance
后,点击 <button>add 1</button>
触发更新:
能够看到,没有任何 walk
、walkChildren
(或相似遍历过程),只调用了reactiveEffect
一个办法就更新了DOM
。
这意味着 mount
时的深度优先遍历建设了 状态
与更新 DOM 的办法
之间一一对应的关系。
因为对应关系确定了,就不再须要额定的遍历过程确定须要变动的DOM
。
当更新 状态
后,只须要找到与他有关系的 更新 DOM 的办法
执行就行。
比方:将 count
状态与如下函数建立联系:
function setCount(value) {p.textContent = value;}
每当 count
变动后调用 setCount(count)
就能更新 p
对应DOM
。
所以,petite-vue
的工作原理,次要包含两点:
mount
时深度优先遍历DOM
,对有状态的DOM
(比方<p>{{count}}</p>
)建设状态
与更新 DOM 的办法
之间一一对应的关系update
时找到该状态
对应的更新 DOM 的办法
并执行
能够看到,即便不深刻源码,也能大体理解工作流程。
如果你想更进一步,比方理解 关系是如何建设的 (波及到 响应式更新),那么就须要深刻源码了。
这里举荐 Vue Mastery
的Vue 3 Reactivity
课程,能够补齐 响应式更新 这块常识。
总结
本文介绍了简单框架源码的浏览方法 —— 即从形象到具体。
- 从
mount
时与update
时的调用栈推导出整体工作流程
- 从
整体工作流程
中发现外围常识 —— 响应式更新
当把握 整体工作流程
与响应式更新
后,再浏览本人感兴趣的局部才不至于陷入宏大的代码量中。
你,学废了么?