render流程之processComponent
2020-10-27 23:59:23 0 举报
vue3 render流程
作者其他创作
大纲/内容
initSlots,对vnode.children的处理,被instance.slots所引用,并且设置InternalObjectKey: 1属性
instance.next = instance.vnode设置instance.next
updateComponentPreRender更新instance
font color=\"#ff9933\
callHookFromMixins,调用本身vnode.type.mixins的beforeCreate钩子
①vnode是通过使用@vue/runtime-dom 的h 函数,传入组件生成,比如font color=\"#000000\
if(minxins || extends)
if(vnode.props.onVnodeBeforeMount)
if(instance.bm)
const prodEffectOptions = { scheduler: queueJob}当effect被trigger的时候,会执行queueJob(effect)
vnode不为空
如果当前effect被trigger触发
const hooks = target[type] || (target[type] = [])const wrappedHook = hook.__weh || hook.__weh = (...args: unknown[]) => { ... })hooks.push(wrappedHook)
if(vnode.mixins)
updateProps
isFunction(setupResult)
queue.push(effect)这里会避免当前effect被重复添加进queue
processElement
font color=\"#ff8000\
callHookFromMixins,调用全局mixin的beforeCreate钩子
flushJobs()取消Pending,设置事件状态为Flushing因为组件更新是从父到子的,所以事件队列需要做一个根据id的排序,比如这里是effect.id,id从小到大。执行effect,完成后取消Flushing状态。
callSyncHook(font color=\"#7f00ff\
else
options的五类属性:数据:data、 props、 propsData、 computed、methods、 Watch DOM: el、 template、 render、 renderError 生命周期钩子: beforeCreate、 created、beforeMount、 mounted、 beforeUpdate、 updated、activated、 deactivated、 beforeDestroy、 destroyed、errorCaptured
createHook(LifecycleHooks.UPDATED)
n1 !== null
createComponentInstance 创建instance,一个组件相关的Object
vnode空,且container._vnode 存在
...省略
normalizePropsOptions
这里如果内部使用this,那么都会指向instance.proxy详情可以查看PublicInstanceProxyHandlers
vnode.el = instance.subTreeif (m) {font color=\"#000000\
reactive中diff算法会解释,因为这里使用的是runtime-core而不是runtime-test 所以appendChild和insertBefore是DOM的原生操作
!asMixin
queueFlush()该方法利用microtask(就是promise)来执行flushJobs,并且设置当前事件状态为pending,凡是pending状态和事件进行中的状态,都不会执行flushJobs()。tips: 这里如果想调试Priomise,可以在flushJobs打上debugger
n1 == null
就是设置instance.u = []instance.u.push(CLICKEVENT)可以去看instance.u字段
vue2.x相关
!instance.render
handleSetupResult
mountElement
api的钩子
const nextTree = renderComponentRoot(instance)更新子组件
调用vnode.type.extends中的beforeCreate钩子
initProps 对vnode.props进行一层的shallowReactive的处理,最后由instance.props引用经过setFullProps处理过的attrs,被instance.attrs 引用
let root = result
这里的patch对应的第一次是processComponent第二次是processElement
instance.next = n2使用invaliddateJob(instance.update)删除queue中的本身update effect更新事件。想知道为什么,去看gitbook的runtime,事件队列。
unmount(font color=\"#3333ff\
查看instance数据字段解释
fallthroughAttrs = Component.props ? attrs : getFallthroughAttrs(attrs)没有设置instance.attrs就直接取props
如组件未挂载
true
setupStatefulComponent
componentEffect
patch,container,原本的vnode可以用n1来表示,新传入进来的vnode可以用n2来表示,如果存在n1且font color=\"#9933ff\
setup设置中currentInstance为当前instance
STATEFUL_COMPONENT
利用callSyncHook钩子调用的过程,这里的钩子比setup中使用api的钩子要提早执行
判断n1是否为空,如果为空且且n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE调用mountComponent,使n2挂载到container中,如果n1不为空则调用font color=\"#9933ff\
invokeArrayFnc(instance.bm)
// updateComponent // This is triggered by mutation of component's own state (next: null) // OR parent calling processComponent (next: VNode)
setupRenderEffect
createSetupContext(instance)
if(needCastKeys)
shallowReactive,被setFullProps处理过的vnode.props进行shallowReactive后被instance.props引用
这里的props是已经调用过的值,所以不会存在响应式数据track的情况,props全部都会被设置成原生dom的数据,这里的onclick事件也被植入当前el,点击元素将会触发
el = vnode.el = hostCloneNode(vnode.el)
需要修改成驼峰大写,才赋值給props,否则赋值給attrs
processComponent
setup返回的可以是function也可以是一个object,如果是object,就设置成响应式对象
mountComponent
vnode.props中的钩子
else && setup
isMounted 已挂载
callSyncHookfont color=\"#ff66b3\
①
invokeArrayFns(bu)
github:https://github.com/Kingbultsea/vue3-analysis语雀:https://www.yuque.com/alipayrx5hwyqw4q/tg3ni5欢迎大家一起编写,或者有疑问的可以提出,大家一起交流!
container._vnode = vnode
setupComponent,对attrs的一些处理 还有setup的处理 instance.type中的所有关键词字段的处理
normalizeObjectSlots / normalizeVNodeSlots
else if (isObject(setupResult))
②
这里可以看到父组件中调用子组件,传入的props与本身vnode的props合并(看 2 patch initialProps部分)
next.props.onVnodeBeforeUpdate
normalized && hasOwn(font color=\"#000099\
setFullProps,设置font color=\"#ff0000\
updateComponent
setup设置
instance.subTree = renderComponentRoot(instance)等待返回result
如果setup内部有钩子,比如当前测试用例调用了onUpdated(CLICKEVENT)钩子
if(isStateful)
处理模板组件vnode.type.template相关,可以先忽略
instance.next
对应的测试用例为runtime-core包中的rendererAttrsFallthrough.spec.ts
if(vnode.type.extends)
result = normalizeVNode(font color=\"#ff8000\
fallthroughAttrs
根据n2的type与shapeFlag类型,来决定进行哪种渲染过程,如当前decode shapeFlag 为ShapeFlags.COMPONENT(vnode的shapeFlage,在生成vnode的时候,会根据type的类型生成相应的shapeFlage,然后通过normalizeChlidren来encode shapeFlage,主要用来标准化组件,因为vnode可能是数组,可能是functional,可能是对象,这里讨论的是对象,上面有说明)
调用vnode.type中自身的beforeCreate
n1 == null && !(n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE)
设置font color=\"#ff8000\
if(props.onVnodeBeforeMount)
shapeFlag & ShapeFlags.ELEMENT
③
if(!setup)
isPromise(setupResult) && setup
finishComponentSetup
这里步骤是渲染setup返回的vnode,然后用新旧交给patch来决定需要不需要更新
setup.length 1
instance.setupState = reactive(setupResult)
props[camelKey] = value
循环
flushPostFlushCbs() // 这里会执行vnodeHook中的mounted updated// postFlushCbs才会执行
vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT 只要是vnode.type 是 object 都是stateful_component
local mixin自身的mixin
currentInstance = instancefont color=\"#ff8000\
这块需要了解trigger trackeffect概念。详情查看响应式数据章节
nextVNode.component = instance const prevProps = instance.vnode.props instance.vnode = nextVNode instance.next = null font color=\"#ff0000\
result = normalizeVnode( instance.render.call(font color=\"#ff8000\
instance.render = setupResult as InternalRenderFunction设置instance.render
warning该功能还未支持
applyMixins
currentInstance = instance这里使用钩子api的时候会使用到pauseTracking() 暂停track,reactive相关,这里停止track是避免执行setup方法的时候,有响应式数据追踪到其他地方的effect,比如具有父组件进行componentEffect的过程中会patch子组件,子组件更新,父组件也需要更新,这一步仅仅在componentEffect中处理。setupResult = callWithErrorHandling调用组件的setup方法,传入font color=\"#ff8000\
0 条评论
下一页