基本示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="components-demo">
<button-counter></button-counter>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
/* 定义一个名为button-counter的组件 */
Vue.component('button-counter', {
data: function() {
return {
count: 0
}
},
template: '<button v-on:click="count++">You click me {{count}} times.</button>'
})
new Vue({
el:'#components-demo'
})
</script>
</body>
</html>
组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 <button-counter>
。我们可以在一个通过 new Vue
创建的 Vue 根实例中,把这个组件作为自定义元素来使用。
因为组件是可复用的 Vue 实例,所以它们与 new Vue
接收相同的选项,例如 data
、computed
、watch
、methods
以及生命周期钩子等。仅有的例外是像 el
这样根实例特有的选项。
组件的复用
你可以将组件进行任意次数的复用:
<div id="components-demo">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
注意当点击按钮时,每个组件都会各自独立维护它的 count
。因为你每用一次组件,就会有一个它的新实例被创建。
data必须是一个函数
当我们定义这个 <button-counter>
组件时,你可能会发现它的 data
并不是像这样直接提供一个对象:
data: {
count: 0
}
取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:
data: function () {
return {
count: 0
}
}
组件的组织
通常一个应用会以一棵嵌套的组件树的形式来组织:
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。
至此,我们的组件都只是通过 Vue.component
全局注册的。
全局注册的组件可以用在其被注册之后的任何 (通过 new Vue
) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。(Vue根实例的组件树)
组件注册
组件名
在注册一个组件的时候,我们始终需要给它一个名字。
Vue.component('my-component-name', { /* ... */ })
该组件名就是 Vue.component
的第一个参数。
组件名的大小写
定义组件名的方式有两种:
使用 kebab-case
Vue.component('my-component-name', { /* ... */ })
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>
。
使用 PascalCase
Vue.component('MyComponentName', { /* ... */ })
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 <my-component-name>
和 <MyComponentName>
都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
所以尽量在使用时采用短横线分隔命名法。
全局注册
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>
这三个组件在各自内部也都可以相互使用。(每个组件必须只有一个根元素)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="components-demo">
<my-component-a></my-component-a>
<my-component-b></my-component-b>
<my-component-c></my-component-c>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('my-component-a', {
template:'<h3><my-component-c></my-component-c></h3>'
});
Vue.component('my-component-b', {
template:'<my-component-a></my-component-a>'
});
Vue.component('my-component-c', {
template:'<span>c</span>'
})
new Vue({
el:'#components-demo'
})
</script>
</body>
</html>
局部注册
你可以通过一个普通的 JavaScript 对象来定义组件:
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
然后在 components
选项中定义你想要使用的组件:
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
对于 components
对象中的每个 property 来说,其 property 名就是自定义元素的名字,其 property 值就是这个组件的选项对象。
注意局部注册的组件在Vue根实例的子组件中不可用。
如果你希望 ComponentA
在 ComponentB
中可用,则你需要这样写:
var ComponentA = { /* ... */ }
var ComponentB = {
components: {
'component-a': ComponentA
},
// ...
}
或者如果你通过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
// ...
}
注意在 ES2015+ 中,在对象中放一个类似 ComponentA
的变量名其实是 ComponentA: ComponentA
的缩写。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="components-demo">
<component-a></component-a>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var ComponentB = {
template: '<div>局部组件B</div>'
}
var ComponentA = {
data: function() {
return {
msg: '局部组件A'
}
},
components:{
'component-b':ComponentB
},
template:'<div>{{msg}}<component-b></component-b></div>'
}
new Vue({
el:'#components-demo',
components:{
'component-a': ComponentA
}
})
</script>
</body>
</html>
组件模板抽离
在组件中写template模板的HTML代码是一件十分麻烦的事,特别不方便。
Vue提供了两种方案写HTML代码
- 使用script标签(不常用)
- 使用template标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<my-component></my-component>
</div>
<!-- 使用template标签 -->
<template id="my-component-template">
<div>
<h2>我是全局组件标题</h2>
<p>我是内容</p>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
/* 注册全局组件:组件与模板分离 */
Vue.component('my-component', {
template: '#my-component-template',
});
const app = new Vue({
el: '#app',
})
</script>
</body>
</html>