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 */)
}
...
}
}
浙公网安备 33010602011771号