注册全局和局部组件
我们已通过 Vue.component()
、普通 JavaScript
对象或单文件组件引擎创建了众多组件。其中部分属于全局组件,另一些则是局部组件。例如,前文在 /components/
目录中重构的所有组件都属于局部组件,而 "什么是组件?" 章节创建的组件则属于全局组件。无论全局还是局部组件,使用时都必须进行注册——有些在创建时即完成注册,有些则需要手动注册。
在接下来的章节中,您将学习:
-
如何进行全局注册与局部注册
-
两种注册方式对应用的影响差异
-
Vue
组件的注册机制(而非组件传递方式)
我们将重点探讨 Vue
组件的注册体系,而非组件间的数据传递机制。值得注意的是,全局组件通过 Vue.component()
方法注册后可在任意 Vue
实例中使用,而局部组件则需通过 components
选项在特定父组件中显式注册才能使用。这种设计既保证了常用组件的全局可用性,又能有效控制专用组件的使用范围。
在 Vue 中注册全局组件
全局组件,顾名思义,可以在整个应用中全局使用。它们通过 Vue.component()
方法进行全局注册:
Vue.component('my-component-name', { ... })
全局组件必须在根 Vue
实例实例化之前完成注册。注册后,它们就可以在根 Vue
实例的模板中使用,例如:
Vue.component('component-x', { ... })
Vue.component('component-y', { ... })
Vue.component('component-z', { ... })
new Vue({ el: '#app' })
<div id="app">
<component-x></component-x>
<component-y></component-y>
<component-z></component-z>
</div>
可以看到,全局组件的注册非常简单——您甚至可能在创建时都没有意识到注册过程。我们稍后将在 "在 Nuxt 中注册全局组件" 章节探讨这种注册方式在 Nuxt
中的应用。不过现在,让我们先学习如何注册局部组件。
在 Vue/Nuxt 中注册局部组件
我们在本章的 Vue
和 Nuxt
应用中已经接触并使用过局部组件。这些组件通过普通 JavaScript
对象创建:
var ComponentX = { ... }
var ComponentY = { ... }
var ComponentZ = { ... }
然后通过 components
选项进行注册:
new Vue({
el: '#app',
components: {
'component-x': ComponentX,
'component-y': ComponentY,
'component-z': ComponentZ
}
})
还记得在 "使用 props 向子组件传递数据" 章节开头创建的 Vue
应用吗?(位于本书 GitHub
仓库的 /chapter-5/vue/component/basic.html
文件)。该应用中的 user-item
组件是个全局组件,现在让我们将其重构为局部组件:
-
移除以下全局组件声明:
Vue.component('user-item', { props: ['user'], template: '<li>{{ user.name }}</li>' })
-
替换为局部组件:
const UserItem = { props: ['user'], template: '<li>{{ user.name }}</li>' }
-
通过
components
选项注册局部组件:new Vue({ el: '#app', data: { users: [ { id: 0, name: 'John Doe' }, //... ] }, components: { 'user-item': UserItem } })
应用功能保持不变,唯一区别是 user-item
组件不再全局可用。这意味着它不能在其他子组件中使用。例如,若要让 ComponentX
在 ComponentZ
中可用,需要手动 "附加":
var ComponentX = { ... }
var ComponentZ = {
components: {
'component-x': ComponentX
}
}
如果使用 babel
和 webpack
编写 ES2015
模块,可以将 ComponentX
作为单文件组件导入:
// components/ComponentZ.vue
import ComponentX from './ComponentX.vue'
export default {
components: {
'component-x': ComponentX
}
}
<component-x
v-for="item in items"
...
></component-x>
还可以省略 components
选项中的 component-x
键名,直接使用 ComponentX
变量:
// components/ComponentZ.vue
export default {
components: {
ComponentX
}
}
在 ES2015+
中,这种写法等价于 ComponentX: ComponentX
。由于 component-x
未注册,模板中需要使用 <ComponentX>
而非 <component-x>
:
<ComponentX
v-for="item in items"
...
></ComponentX>
上述单文件组件的 ES2015
写法与我们在 Nuxt
中编写 .vue
文件的方式完全一致。至此您应该意识到,我们在 Nuxt
应用中(如 /components/copyright.vue
和 /components/nav.vue
)编写的都是局部组件。那么在 Nuxt
中如何编写全局组件呢?这就需要用到 /plugins/
目录了,我们将在下一节详细探讨。
您可以在本书 |
在 Nuxt 中注册全局组件
我们在第 2 章《Nuxt
入门》中学习过目录结构,其中 /plugins/
目录可用于存放需要在根 Vue
应用实例化之前运行的 JavaScript
文件。因此,这里正是注册全局组件的最佳位置。
让我们创建第一个全局组件:
-
在
/plugins/
目录创建简单Vue
组件:<!-- components/global/sample-1.vue --> <template> <p>{{ message }}</p> </template> <script> export default { data () { return { message: 'A message from sample global component 1.' } } } </script>
-
在
/plugins/
目录创建.js
文件并导入组件:// plugins/global-components.js import Vue from 'vue' import Sample from '~/components/global/sample-1.vue' Vue.component('sample-1', Sample)
-
也可以在
/plugins/global-components.js
中直接创建第二个全局组件:Vue.component('sample-2', { render (createElement) { return createElement('p', 'A message from sample global component 2.') } })
-
在
Nuxt
配置文件中设置这些插件优先运行:// nuxt.config.js plugins: [ '~/plugins/global-components.js', ]
请注意,这个组件将在你的
Nuxt
应用的客户端和服务器端都可用。如果你只想在特定的端运行这个组件,例如只在客户端,那么你可以像下面这样注册它:// 仅客户端 { src: '~/plugins/global-components.js', mode: 'client' } // 仅服务端 { src: '~/plugins/global-components.js', mode: 'server' }
-
全局组件无需重复导入即可随处使用:
<!-- pages/about.vue --> <sample-1 /> <sample-2 />
-
运行应用后将显示:
<p>A message from sample global component 1.</p> <p>A message from sample global component 2.</p>
就这样!这就是你如何在 Nuxt
中通过涉及各种文件来注册全局组件的方法。全局注册的本质是使用 Vue.component
,就像我们在 Vue
应用中做的那样。然而,全局注册通常不是理想的选择,就像它的 “近亲” ——全局混入(我们将在下一节中介绍)一样。例如,在大多数情况下不需要全局注册组件对于服务器端和客户端来说都是不必要的。现在,让我们继续看看什么是混入以及如何编写它们。
您可以在本书 |