Vue2源码的一些个人解读 - 1)Vue组件最终是怎么协助真实dom渲染到浏览器上的

1,Vue组件最终是怎么协助真实dom渲染到浏览器上的(第一次渲染为例)

我们知道Vue的渲染是父组件patch子组件,最终到真实dom,假如生成了真实dom的,此时他的父组件并不是真实存在的,那么值是怎么传递的呢?
总结起来就是,父组件初始化时生成自己的$el,真实dom生成后将自己赋值给$parent.$el。
关键代码如下所示:
vue/src/core/instance/lifecycle.js

Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
   ...
   vm._vnode = vnode
   ...
   // if parent is an HOC, update its $el as well
   // 这里将真实dom赋值给父组件,父组件一直赋值给他的上级,一直到真实dom
   if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
     vm.$parent.$el = vm.$el
   }
 }

vue/src/core/instance/render.js

export function initRender (vm: Component) {
 
 vm._vnode = null // the root of the child tree
 ...
 // 子组件$vnode赋值为options的_parentVnode
 const parentVnode = vm.$vnode = options._parentVnode // the placeholder node in parent tree
 ...

}

vue/src/core/vdom/create-component.js

const componentVNodeHooks = {
 init (vnode: VNodeWithData, hydrating: boolean): ?boolean {
   if (
     vnode.componentInstance &&
     !vnode.componentInstance._isDestroyed &&
     vnode.data.keepAlive
   ) {
     // kept-alive components, treat as a patch
     const mountedNode: any = vnode // work around flow
     componentVNodeHooks.prepatch(mountedNode, mountedNode)
   } else {
     // 父组件patch子组件时将自己的vnode传给子组件
     const child = vnode.componentInstance = createComponentInstanceForVnode(
       vnode,
       activeInstance
     )
     child.$mount(hydrating ? vnode.elm : undefined, hydrating)
   }
 },
}
export function createComponentInstanceForVnode (
 vnode: any, // we know it's MountedComponentVNode but flow doesn't
 parent: any, // activeInstance in lifecycle state
): Component {
 //赋值 _parentVnode
 const options: InternalComponentOptions = {
   _isComponent: true,
   _parentVnode: vnode,
   parent
 }
 // check inline-template render functions
 const inlineTemplate = vnode.data.inlineTemplate
 if (isDef(inlineTemplate)) {
   options.render = inlineTemplate.render
   options.staticRenderFns = inlineTemplate.staticRenderFns
 }
 return new vnode.componentOptions.Ctor(options)
}

vue/src/core/vdom/patch.js

function createComponent (vnode, insertedVnodeQueue, parentElm, refElm) {
   let i = vnode.data
   if (isDef(i)) {
     const isReactivated = isDef(vnode.componentInstance) && i.keepAlive
     if (isDef(i = i.hook) && isDef(i = i.init)) {
       // 这里传值
       i(vnode, false /* hydrating */)
     }
     ...
   }
 }
posted @ 2021-02-02 18:04  jakkiyui  阅读(86)  评论(0)    收藏  举报