Vue为了解耦,将逻辑分成了两个模块
运行时 (不依赖平台的browser),主要靠的是虚拟dom,它是可以跨平台的
针对不同平台的运行时,vue就是针对浏览器平台的
runtime-dom提供一个渲染器,这个渲染器可以渲染虚拟dom节点到指定的容器中。
官方提供
根据用户传入的内容进行渲染
我们实现这个runtime-dom,创建runtime-dom文件夹
创建src文件夹,下面创建index.ts,以及nodeOps.ts提供一些对节点的操作
插入节点
anchor是插入参照物,可以为null,当anchor参数为null的时候,inserBefore等同于appendChild
创建元素
创建文本
删除节点
设置元素内容
设置文本节点
查询节点
查询父节点
查询兄弟节点
上述是对节点的一些操作,下面我们来写对属性的一系列操作,创建patchProp.ts文件以及ptachProp需要调用的一些方法单独抽离的文件
编写patchProp方法
整合nodeOps和patcProp
我们现在来详细写patchProp
首先判断key的类型,分别交由不同的函数处理
区分是class、style、事件和普通属性
处理class
新改了值直接覆盖class
新值是null,说明是删除操作,直接删除
处理style
循环最新值,把所有新值全部覆盖即可
去除之前有的,新的没有的属性
处理事件
如果没绑定过事件
我们可以在元素上绑定一个_vei来记录元素绑定过的事件
判断这个事件名是否存在,如果不存在,拿到新事件名字,on后面的值
然后判断当前的新的事件是否有值,如果有值,我们用createInvoker处理事件值后,缓存到invokers中
然后绑上事件
如果新设置的事件值为空,那么就解绑事件,然后清空缓存区里这个事件
createInvoker这种写法有利于我们换绑事件,如果不这样写,那么我们每次更改事件的时候都需要先解绑,再绑新事件。
如果绑定过事件并且也设置了新值
更换缓存区中该事件invoker的value值,更改为新值就可以了
createInvoker里为每一个事件创造了一个空函数,这个空函数的返回值调用这个空函数的value,而我们设置的事件就存在这个空函数的value属性上,这种操作有利于我们换绑事件
处理属性
如果新值有值,我们就直接设置到元素上
如果没有,我们就删掉
runtime-dom还提供一个api,render
render内部帮我们调用createRenderer后调用它的render进行渲染
createRenderer方法和h方法其实都不是在runtime-dom里实现,他俩是在runtime-core里实现的,因为渲染器他们本身是和平台无关的,你给我的是dom渲染还是canvas等,他们是不关心的
我们现在创建runtime-core模块
我们下一章再实现h方法和createVnode方法
总结
runtime-dom本质上没做什么,它只是封装了一些平台对应的代码,它封装好以后,内部去调用创建渲染器去进行一个渲染,那具体怎么渲染是内部去做的,内部runtime-core去根据你传进来的一些属性操作、事件操作和dom操作等等方法,把传进来元素生成的vnode虚拟节点,然后放进对应的容器中就可以了。所以runtime-dom跟平台有关,而runtime-core跟平台无关。