1. 前言
本节我们将介绍如何使用组件(Component),组件是 Vue.js 最强大的功能之一,组件可以扩展 HTML 元素,封装可重用的代码。组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:

如何规划和设计组件是学习组件的难点,在编写组件时,我们需要不断思考如何提高组件的可复用性。
2. 官方解释
组件是可复用的 Vue 实例,且带有一个名字。 —— 官方定义
组件是可复用的 Vue 实例, 我们可以把页面中在多个场景中重复使用的部分,抽出为一个组件进行复用。组件大大提高了代码的复用率。
3. 组件的注册
3.1. 全局组件注册
我们可以通过调用 Vue.component
的方式来定义全局组件,它接收两个参数:1. 组件名,2. 组件属性对象。
命名:
- 短横线:
<my-component-name>
- 驼峰式:
<MyComponentName>
使用驼峰命名组件时,首字母最好以大写字母开头。
属性对象:组件的属性对象即为 Vue
的实例对象属性。
全局组件可以在任何其他组件内使用,所以当我们设计的组件,需要在不同地方使用的时候,我们应当注册全局组件。
// 注册// 驼峰命名Vue.component('MyComponentName', {/* */})// 短横线命名Vue.component('my-component-name', {/* */})......// 使用<my-component-name></my-component-name>// 也可以使用自闭和的方式<my-component-name />// 注册 // 驼峰命名 Vue.component('MyComponentName', {/* */}) // 短横线命名 Vue.component('my-component-name', {/* */}) ...... // 使用 <my-component-name></my-component-name> // 也可以使用自闭和的方式 <my-component-name />// 注册 // 驼峰命名 Vue.component('MyComponentName', {/* */}) // 短横线命名 Vue.component('my-component-name', {/* */}) ...... // 使用 <my-component-name></my-component-name> // 也可以使用自闭和的方式 <my-component-name />
具体示例如下:实例演示
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><my-component></my-component><my-component /></div></body><script src="https://unpkg.com/vue/dist/vue.js"></script><script type="text/javascript">Vue.component('myComponent', {template: '<div>Hello !</div>'})var vm = new Vue({el: '#app',data() {return {}}})</script></html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component></my-component> <my-component /> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { template: '<div>Hello !</div>' }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component></my-component> <my-component /> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { template: '<div>Hello !</div>' }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html>
代码解释:
JS 代码第 3-5 行,我们注册了一个全局组件 myComponent,并在 html 内使用两种方式引用了该组件。
3.1. 局部组件注册
我们也可以在 Vue
实例选项中注册局部组件,这样组件只能在这个实例中使用。局部组件的注册利用 Vue
实例的 components
对象属性,以组件名作为 key
值,以属性对象作为 value
。由于局部组件只能在当前的 Vue
实例中使用,所以当我们设计的组件不需要在其他组件内复用时,可以设计为局部组件。
//注册components: {'MyComponentName': {template: '<div>Hello !</div>'}}......// 使用<my-component-name></my-component-name>// 也可以使用自闭和的方式<my-component-name />//注册 components: { 'MyComponentName': { template: '<div>Hello !</div>' } } ...... // 使用 <my-component-name></my-component-name> // 也可以使用自闭和的方式 <my-component-name />//注册 components: { 'MyComponentName': { template: '<div>Hello !</div>' } } ...... // 使用 <my-component-name></my-component-name> // 也可以使用自闭和的方式 <my-component-name />
具体示例如下:实例演示
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><my-component></my-component><my-component /></div></body><script src="https://unpkg.com/vue/dist/vue.js"></script><script type="text/javascript">var vm = new Vue({el: '#app',components: {'myComponent': {template: '<div>Hello !</div>'}}})</script></html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component></my-component> <my-component /> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', components: { 'myComponent': { template: '<div>Hello !</div>' } } }) </script> </html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component></my-component> <my-component /> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', components: { 'myComponent': { template: '<div>Hello !</div>' } } }) </script> </html>
代码解释:
JS 代码第 5-9 行,我们在当前实例上注册了一个局部组件 myComponent,并在 html 内使用两种方式引用了该组件。
4. 组件中的属性参数
在之前章节我们学习了 Vue
实例,其实,所有的 Vue
组件也都是 Vue
的实例,他们也可以接收同样的属性参数,并且有相同的生命周期钩子。
示例:实例演示
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><my-component></my-component></div></body><script src="https://unpkg.com/vue/dist/vue.js"></script><script type="text/javascript">Vue.component('myComponent', {template: '<div><div>{{ count }}</div><button @click="add">添加次数</button></div>',data() {return {count: 10}},methods: {add() {this.count = this.count + 1;}},created() {console.log('组件myComponent:created')}})var vm = new Vue({el: '#app',data() {return {}}})</script></html>12345678910111213141516171819202122232425262728293031323334353637383940<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component></my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { template: '<div><div>{{ count }}</div><button @click="add">添加次数</button></div>', data() { return { count: 10 } }, methods: { add() { this.count = this.count + 1; } }, created() { console.log('组件myComponent:created') } }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html> 12345678910111213141516171819202122232425262728293031323334353637383940<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component></my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { template: '<div><div>{{ count }}</div><button @click="add">添加次数</button></div>', data() { return { count: 10 } }, methods: { add() { this.count = this.count + 1; } }, created() { console.log('组件myComponent:created') } }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html> 12345678910111213141516171819202122232425262728293031323334353637383940
代码解释:
JS 代码第 3-18 行,注册了一个全局组件 myComponent,并定义了 data 数据、 methods 方法、created 生命周期函数。
5. 组件的复用
你可以将组件进行任意次数的复用,他们之间相互独立,互不影响:实例演示
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><div id="app"><my-component></my-component><my-component></my-component><my-component></my-component></div></body><script src="https://unpkg.com/vue/dist/vue.js"></script><script type="text/javascript">Vue.component('myComponent', {template: '<div><div>{{ count }}</div><button @click="add">添加次数</button></div>',data() {return{count: 10}},methods: {add() {this.count = this.count + 1;}},})var vm = new Vue({el: '#app',data() {return {}}})</script></html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component></my-component> <my-component></my-component> <my-component></my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { template: '<div><div>{{ count }}</div><button @click="add">添加次数</button></div>', data() { return{ count: 10 } }, methods: { add() { this.count = this.count + 1; } }, }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <my-component></my-component> <my-component></my-component> <my-component></my-component> </div> </body> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('myComponent', { template: '<div><div>{{ count }}</div><button @click="add">添加次数</button></div>', data() { return{ count: 10 } }, methods: { add() { this.count = this.count + 1; } }, }) var vm = new Vue({ el: '#app', data() { return {} } }) </script> </html>
代码解释:
html 代码第 2-4 行,我们来使用三次组件 myComponent。他们之间是相互独立的,当点击按钮时,每个组件都会各自独立维护它的 count。因为我们每使用一次组件,就会有一个它的新实例被创建。
5.1 组件中的 data 必须是一个函数
当我们定义这个 <myComponent>
组件时,你可能会发现它的 data 并不是像这样直接提供一个对象:
data: {count: 0}data: { count: 0 }data: { count: 0 }
这是因为,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:
data: function () {return {count: 0}}data: function () { return { count: 0 } }data: function () { return { count: 0 } }
暂无评论内容