Close
升级到 Vue 3 | Vue 2 EOL

组件注册

本页假设您已经阅读了 组件基础。如果您是组件新手,请先阅读该内容。

组件名称

注册组件时,它将始终被赋予一个名称。例如,在迄今为止我们看到的全局注册中

Vue.component('my-component-name', { /* ... */ })

组件的名称是 Vue.component 的第一个参数。

您为组件指定的名称可能取决于您打算在何处使用它。当直接在 DOM 中使用组件(而不是在字符串模板或 单文件组件 中)时,我们强烈建议您遵循 W3C 规则 用于自定义标签名称(全部小写,必须包含连字符)。这有助于您避免与当前和将来的 HTML 元素发生冲突。

您可以在 样式指南 中看到组件名称的其他建议。

名称大小写

定义组件名称时,您有两个选择

使用连字符命名法

Vue.component('my-component-name', { /* ... */ })

当使用连字符命名法定义组件时,您也必须在引用其自定义元素时使用连字符命名法,例如在 <my-component-name> 中。

使用帕斯卡命名法

Vue.component('MyComponentName', { /* ... */ })

当使用帕斯卡命名法定义组件时,您可以在引用其自定义元素时使用任一大小写。这意味着 <my-component-name><MyComponentName> 都是可接受的。但是请注意,只有连字符命名法的名称在 DOM 中直接有效(即非字符串模板)。

全局注册

到目前为止,我们只使用 Vue.component 创建组件

Vue.component('my-component-name', {
// ... options ...
})

这些组件是 全局注册 的。这意味着它们可以在注册后创建的任何根 Vue 实例(new Vue)的模板中使用。例如

Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })

new Vue({ el: '#app' })
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>

这甚至适用于所有子组件,这意味着所有这三个组件也将在 彼此内部 可用。

局部注册

全局注册通常并不理想。例如,如果您使用的是像 Webpack 这样的构建系统,全局注册所有组件意味着即使您停止使用某个组件,它也可能仍然包含在您的最终构建中。这会不必要地增加用户必须下载的 JavaScript 量。

在这些情况下,您可以将组件定义为纯 JavaScript 对象

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

然后定义您想在 components 选项中使用的组件

new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})

对于 components 对象中的每个属性,键将是自定义元素的名称,而值将包含组件的选项对象。

请注意,局部注册的组件不会在子组件中可用。例如,如果您想在 ComponentB 中使用 ComponentA,您需要使用

var ComponentA = { /* ... */ }

var ComponentB = {
components: {
'component-a': ComponentA
},
// ...
}

或者,如果您使用的是 ES2015 模块,例如通过 Babel 和 Webpack,它可能看起来更像

import ComponentA from './ComponentA.vue'

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

请注意,在 ES2015+ 中,将像 ComponentA 这样的变量名放在对象中是 ComponentA: ComponentA 的简写,这意味着变量的名称既是

模块系统

如果您没有使用带有 import/require 的模块系统,您现在可能可以跳过本节。如果您正在使用,我们有一些专门针对您的说明和技巧。

模块系统中的局部注册

如果您仍然在这里,那么您可能正在使用模块系统,例如使用 Babel 和 Webpack。在这些情况下,我们建议您创建一个 components 目录,每个组件都在自己的文件中。

然后,您需要导入您想使用的每个组件,然后才能局部注册它。例如,在假设的 ComponentB.jsComponentB.vue 文件中

import ComponentA from './ComponentA'
import ComponentC from './ComponentC'

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

现在,ComponentAComponentC 都可以在 ComponentB 的模板中使用。

基础组件的自动全局注册

您的许多组件将是比较通用的,可能只包装一个元素,比如输入或按钮。我们有时将这些称为 基础组件,它们往往在您的组件中非常频繁地使用。

结果是,许多组件可能包含很长的基础组件列表

import BaseButton from './BaseButton.vue'
import BaseIcon from './BaseIcon.vue'
import BaseInput from './BaseInput.vue'

export default {
components: {
BaseButton,
BaseIcon,
BaseInput
}
}

只是为了支持模板中相对较少的标记

<BaseInput
v-model="searchText"
@keydown.enter="search"
/>
<BaseButton @click="search">
<BaseIcon name="search"/>
</BaseButton>

幸运的是,如果您使用的是 Webpack(或 Vue CLI 3+,它在内部使用 Webpack),您可以使用 require.context 来全局注册这些非常常见的基组件。以下是一个示例,展示了您可能在应用程序的入口文件(例如 src/main.js)中全局导入基组件的代码

import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'

const requireComponent = require.context(
// The relative path of the components folder
'./components',
// Whether or not to look in subfolders
false,
// The regular expression used to match base component filenames
/Base[A-Z]\w+\.(vue|js)$/
)

requireComponent.keys().forEach(fileName => {
// Get component config
const componentConfig = requireComponent(fileName)

// Get PascalCase name of component
const componentName = upperFirst(
camelCase(
// Gets the file name regardless of folder depth
fileName
.split('/')
.pop()
.replace(/\.\w+$/, '')
)
)


// Register component globally
Vue.component(
componentName,
// Look for the component options on `.default`, which will
// exist if the component was exported with `export default`,
// otherwise fall back to module's root.
componentConfig.default || componentConfig
)
})

请记住,全局注册必须在创建根 Vue 实例(使用 new Vue)之前进行这是一个示例,展示了这种模式在真实项目环境中的应用。