乐趣区

关于javascript:Vue动态组件源码解析

import Vue from 'vue';
import App from './app.vue';
import Home from './home.vue';

new Vue({
    el: '#app',
    data() {
        return {component: App,};
    },
    template: `<div><button @click="toSwitch"> 切换 </button><component :is="component"/></div>`,
    components: {App, Home},// 注册组件,注册的组件名称为 "App"、"Home"
    methods: {toSwitch() {if (this.component === App) {this.component = Home;} else {this.component = App;}
        },
    },
});
<template>
    <div>app</div>
</template>

<script>
    export default {name: 'app',};
</script>
<template>
    <div>home</div>
</template>

<script>
    export default {name: 'home',};
</script>
with (this) {return _c('div', [_c('button', { on: { click: toSwitch} }, [_v('切换')]), _c(component, { tag: 'component'})], 1);
}
  1. 如果 component 标签的 is 属性值是组件选项对象,间接依据该组件选项对象创立节点(VNode 实例)。如果 component 标签的 is 属性值是 components 中注册的组件名称,则依据该组件名称去 components 找到该组件名称对应的组件选项对象,再依据该组件选项对象创立节点。
function _createElement (
  context,comp
  tag,
  data, 
  children,
  normalizationType
) {
  ...
  if (typeof tag === 'string') {
    var Ctor;
    ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag);
    if (config.isReservedTag(tag)) {...} else if ((!data || !data.pre) && isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {/* 依据该组件名称去 components 找到该组件名称对应的组件选项对象 */
      vnode = createComponent(Ctor, data, context, children, tag);
    } else {...}
  } else {
    ...
    vnode = createComponent(tag, data, context, children);// 此时 tag 指向组件选项对象, 间接依据组件选项对象创立节点。data 值为 {tag:"component"}
  }
  ...
}
退出移动版