第一步
用位运算来给虚拟节点加类型,我们先创建ShapeFlag.ts文件
第二步
创建vnode.ts文件写createVNode方法
- 创建一个对象来描述内容,上面的shapeFlag就是我们通过判断type来给虚拟节点增加类型,之后通过&运算我们就知道虚拟节点的类型是什么
然后我们需要对儿子的类型做出判断
- 用虚拟节点自己的类型和儿子的类型做或运算,这样就可以用虚拟节点上的shapeFlag判断出自己当前的类型和儿子的类型
第三步
然后我们回到renderer.ts中去写render方法了,对这个地方没印象的同学可以回到上篇文章去看下
render调用patch方法
- 第一个参数是之前的虚拟节点,初始调用给个null,第二个参数是当前要渲染的虚拟节点,第二个参数是渲染到的容器
patch方法
- 判断虚拟节点中的类型,做对应的处理,用与运算
然后调用processComponent去处理组件,将三个参数传入
processComponent方法
然后判断n1是否存在,如果没有上一次的虚拟节点我们就将n2,也就是新虚拟节点挂载到容器里,调用mountComponent方法
mountComponent方法
createComponentInstance方法
我们继续去写createComponentInstance方法去创建实例
- 主要做的事情就是初始化
setupComponent方法
将数据解析到实例上,给实例赋值
- 从vnode中解析出props和attrs,将它们放到实例上
- 检查当前是不是有状态的组件,通过当前的vnode中shapeFlag,与shapeFlag事先写好的标识组件有状态进行与操作
- 如果当前组件有状态,就调用当前实例的setup方法,用setup的返回值填充
setupStatefulComponent方法
- 获取当前组件的类型,拿到setup方法
- 执行setup方法
- 然后调用组件上的render方法
- instance中的props、attrs、slots、emit、expose会被单独提取出来,因为实际开发中可能会被用到
createSetupContext方法
创建setup的第二个参数,将实例中包含的内容,提取一些传递给context
代理
我们希望当我们访问这个实例上的某个属性,能走我们自己的get方法
现在我们去写这个handlers
PublicInstanceProxyHandlers
- 当我们去访问代理对象proxy中的属性的时候,会分别在setupState、props、data中去寻找,如果找不到就返回undefined
- 设置值也是如此
- 这样写的好处是取值非常方便 然后我们去判断setup是否有,有去执行,没有就完成组件的启动
finishComponentSetup方法
处理setup执行的返回值
handleSetupResult方法
- 判断setup执行返回的结果是否是函数,如果是函数,则赋值给实例的render上
- 判断如果是对象则赋值到setupState上,对这个变量还有印象吧,上下文proxy上查找中会第一个从这里面查找
- 最后调用finishComponentSetup方法
最后总结一下组件的创建流程
- 先创建实例
- 然后把需要的数据解析到实例上,也就是给实例赋值,比如state、props、attrs、render等
- 最后创建一个effect,让render函数执行,这样render方法中拿到的数据就会收集这个effect,属性更新时,effect会重新执行
本篇博文只写了前两步,最后一步,我们下篇博文再实现
如果您觉得有所收获,麻烦动动小手点个攒,谢谢啦~ 预知后事如何,且听下回分解~