跳到主要内容

局部

2023年03月16日
柏拉文
越努力,越幸运

一、认识


全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。

二、语法


2.1 同步

import ComponentA from './ComponentA.vue'

export default {
components: {
"component-a": ComponentA
},
// ...
}

对于 components 对象中的每个 property 来说,其 property 名就是自定义元素的名字,其 property 值就是这个组件的选项对象。或者如果你通过 Babelwebpack 使用 ES2015 模块,那么代码看起来更像:

import ComponentA from './ComponentA.vue'

export default {
components: {
ComponentA
},
// ...
}

注意在 ES2015+ 中,在对象中放一个类似 ComponentA的变量名其实是 ComponentA: ComponentA 的缩写,即这个变量名同时是:

  • 用在模板中的自定义元素的名称

  • 包含了这个组件选项的变量名

2.2 异步

在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。

  • 方式一、工厂函数import: 在工厂函数中返回一个 Promiseimport() 入会返回一个 Promise 对象。这个特殊的 import() 语法将会告诉 webpack。自动将你的构建代码切割成多个包,这些包会通过 Ajax 请求加载

    export default {
    name: 'App',
    components: {
    A: ()=> import("./components/A.vue")
    }
    }
  • 方式二、工厂函数调用resolve回调: 工厂函数会收到一个 resolve 回调,这个回调函数会在你从服务器得到组件定义的时候被调用。你也可以调用 reject(reason) 来表示加载失败。这个特殊的 require 语法将会告诉 webpack。自动将你的构建代码切割成多个包,这些包会通过 Ajax 请求加载

    export default {
    name: "App",
    components: {
    A: (resolve) => {
    setTimeout(() => {
    require(["./components/A"], resolve);
    },3000);
    },
    },
    };
  • 方式三、工厂函数配置加载状态

    components: {
    A: () => {
    return {
    component: import("./components/A.vue"),
    loading: "加载中",
    error: "加载失败",
    delay: 3000,
    timeout: 3000,
    };
    },
    }

三、自动化注册


3.1 Vite 自动化注册

3.2 Webpack 自动化注册

<template>
<div>
<HelloWorld msg="Welcome to Your Vue.js App"/>
<A/>
<B/>
</div>
</template>

<script>

const getComponentName = (fileName) => {
return fileName
.split("/")
.pop()
.replace(/\.\w+$/, "");
};

const components = {};
const requireComponent = require.context("./components", false, /\w+\.(vue)$/);
requireComponent.keys().forEach((fileName) => {
const componentConfig = requireComponent(fileName);
const componentName = getComponentName(fileName);
components[componentName] = componentConfig.default || componentConfig
});

export default {
name: 'App',
components,
}
</script>