很多人认为虚拟 DOM 最大的优势是 diff 算法,减少 JavaScript 操作真实 DOM 的带来的性能消耗。虽然这一个虚拟 DOM 带来的一个优势,但并不是全部。虚拟 DOM 最大的优势在于抽象了原本的渲染过程,实现了跨平台的能力,而不仅仅局限于浏览器的 DOM,可以是安卓和 IOS 的原生组件,可以是近期很火热的小程序,也可以是各种GUI
// DEPRECATED: alias for componentInstance for backwards compat. /* istanbul ignore next https://github.com/answershuto/learnVue*/ get child (): Component | void { returnthis.componentInstance } }
这里对VNode进行稍微的说明:
所有对象的 context 选项都指向了 Vue 实例
elm 属性则指向了其相对应的真实 DOM 节点
vue是通过createElement生成VNode
源码位置:src/core/vdom/create-element.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
exportfunctioncreateElement ( context: Component, tag: any, data: any, children: any, normalizationType: any, alwaysNormalize: boolean ): VNode | Array<VNode> { if (Array.isArray(data) || isPrimitive(data)) { normalizationType = children children = data data = undefined } if (isTrue(alwaysNormalize)) { normalizationType = ALWAYS_NORMALIZE } return_createElement(context, tag, data, children, normalizationType) }
exportfunction_createElement( context: Component, tag?: string | Class<Component> | Function | Object, data?: VNodeData, children?: any, normalizationType?: number ): VNode | Array<VNode> { if (isDef(data) && isDef((data: any).__ob__)) { process.env.NODE_ENV !== 'production' && warn( `Avoid using observed data object as vnode data: ${JSON.stringify(data)}\n` + 'Always create fresh vnode data objects in each render!', context` ) return createEmptyVNode() } // object syntax in v-bind if (isDef(data) && isDef(data.is)) { tag = data.is } if (!tag) { // in case of component :is set to falsy value return createEmptyVNode() } ... // support single function children as default scoped slot if (Array.isArray(children) && typeof children[0] === 'function' ) { data = data || {} data.scopedSlots = { default: children[0] } children.length = 0 } if (normalizationType === ALWAYS_NORMALIZE) { children = normalizeChildren(children) } else if ( === SIMPLE_NORMALIZE) { children = simpleNormalizeChildren(children) } // 创建VNode ... }
// plain options object: turn it into a constructor if (isObject(Ctor)) { Ctor = baseCtor.extend(Ctor) }
// if at this stage it's not a constructor or an async component factory, // reject. if (typeofCtor !== 'function') { if (process.env.NODE_ENV !== 'production') { warn(`Invalid Component definition: ${String(Ctor)}`, context) } return }
// async component let asyncFactory if (isUndef(Ctor.cid)) { asyncFactory = Ctor Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context) if (Ctor === undefined) { returncreateAsyncPlaceholder( asyncFactory, data, context, children, tag ) } }
data = data || {}
// resolve constructor options in case global mixins are applied after // component constructor creation resolveConstructorOptions(Ctor)
// transform component v-model data into props & events if (isDef(data.model)) { transformModel(Ctor.options, data) }
// extract listeners, since these needs to be treated as // child component listeners instead of DOM listeners const listeners = data.on // replace with listeners with .native modifier // so it gets processed during parent component patch. data.on = data.nativeOn
if (isTrue(Ctor.options.abstract)) { const slot = data.slot data = {} if (slot) { data.slot = slot } }