Vue2中引入了virtual dom用来对DOM节点进行描述,我们首先要关注的是如何生层vdom。

首先要解决的一个问题是,创建的vdom,描述的是那种节点。一个vdom可能是描述普通的DOM元素,也可能对应一个组件。

// 下面的tag对应createElement第一个参数,表示节点类型


// 处理抽象组件component 由is属性决定对应的节点
if (isDef(data) && isDef(data.is)) {
    tag = data.is
}
if (!tag) {
// 处理tag是falsy值的情况,业务代码走到这基本就是bug了
    return createEmptyVNode()
}

// createElement第一个参数支持多种类型(字符串、对象、函数)
if (typeof tag === 'string') {
    let Ctor
    ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag)
    if (config.isReservedTag(tag)) {
        // 普通DOM节点
        vnode = new VNode(
            config.parsePlatformTagName(tag), data, children,
                undefined, undefined, context
        )
    } else if (isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {
        // 组件
        vnode = createComponent(Ctor, data, context, children, tag)
    } else {
        // 既不是普通DOM节点,也不是注册的组件,一般是bug了
        vnode = new VNode(
            tag, data, children,
            undefined, undefined, context
            )
    }
} else {
// 一般只有手写render函数才有可能走到这里
// tag应该是一个vue实例的配置项,或者是一个vue子类
// https://github.com/alexjoverm/v-runtime-template 用到了这个特性
    vnode = createComponent(tag, data, context, children)
}

我们注册组件的时候,可能注册的是vue选项,也可能是vue子类,还可能是异步加载函数,createComponent方法就负责对这些情况处理。

if (isUndef(Ctor)) {
    return
}
// 这个是根Vue类
const baseCtor = context.$options._base

// 对象的情况,尝试处理成vue子类
if (isObject(Ctor)) {
    Ctor = baseCtor.extend(Ctor)
}

// 到现在应该都处理成函数的形式了
if (typeof Ctor !== 'function') {
    if (process.env.NODE_ENV !== 'production') {
        warn(`Invalid Component definition: ${String(Ctor)}`, context)
    }
    return
}

// 异步组件 具体内容见下一篇 异步组件
let asyncFactory
// 因为所有的Vue子类都会有cid作为唯一标示
// 没有cid意味着是异步组件
if (isUndef(Ctor.cid)) {
    asyncFactory = Ctor
    Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context)
    if (Ctor === undefined) {
        // 暂时用个空节点占位,如果没有loading component的话
        return createAsyncPlaceholder(
            asyncFactory,
            data,
            context,
            children,
            tag
        )
    }
}

// 生成对应的vnode
const name = Ctor.options.name || tag
const vnode = new VNode(
    `vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
    data, undefined, undefined, undefined, context,
    { Ctor, propsData, listeners, tag, children },
    asyncFactory
)

到现在为止我们确定了vdom描述的是什么节点

results matching ""

    No results matching ""