组件在Vue中是基础功能,在使用中非常方便,想要把vue用好就必须精通组件的使用

组件《Componet》是什么
先看看官方对组件的解释
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用 is
特性进行了扩展的原生 HTML 元素。
所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。
我们了解到以下几点:
- 是封装可重用的HTML:把各个独立的小功能封装为组件,不重复制造轮子
- 是Vue的实例:能够使用Vue的生命周期钩子方法
注册和使用
全局注册
在初始化根实例之前(index.js)注册组件
// 注册
Vue.component('my-component', {
template: '<div>A custom component!</div>',
data: {
message: 'hello'
}
})
局部注册
仅在当前作用域内注册并使用组件
var Child = {
template: '<div>A custom component!</div>'
}// ...
components: {
// <my-component> 将只在父组件模板中可用
'my-component': Child
}
//..
使用已注册组件,包括插件的组件也是如此用法
<div id="example">
<my-component></my-component>
</div>
官方示例
<div id="example-2">
<simple-counter></simple-counter>
<simple-counter></simple-counter>
<simple-counter></simple-counter>
</div>
Vue.component('simple-counter', {
template: '<button v-on:click="counter += 1">{ { counter } }</button>',
// 返回Data对象
data: function () {
return { counter: 0 }
}
})
new Vue({
el: '#example-2'
})
传递数据 props
当组件被调用时可以传递参数,组件根据参数的不同执行不同的操作。这种正向(从上而下)的传递数据过程使用props实现。
<div id="prop-example-2">
<input v-model="parentMsg">
<child my-message="hello"></child>
<!--动态地将 prop 绑定到父组件的数据-->
<child :my-message="parentMsg"></child>
</div>
Vue.component('child', {
// 在 JavaScript 中使用 camelCase
props: ['myMessage'],
template: '<span>{ { myMessage } }</span>'
})
Prop验证
Vue.component('example', {
props: {
// 基础类型检测 (`null` 指允许任何类型)
propA: Number,
// 可能是多种类型
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数值且有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值应当由一个工厂函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
}
})
组件通信
组件通信关系分为父子组件通信、兄弟组件通信、跨级组件通信。
父子组件通信
父子组件通信使用自定义事件方法。自组件用$emit()来触发事件,父组件用$on来舰艇自组件的事件(javascript 观察者模式)。
父组件通过method监听自组件$emit释放的事件,请看例子:
<div id="counter-event-example">
<p>{ { total } }</p>
<button-counter @increment="incrementTotal"></button-counter>
<button-counter @increment="incrementTotal"></button-counter>
</div>
Vue.component('button-counter', {
template: '<button @click="incrementCounter">{ { counter } }</button>',
data: function () {
return {
counter: 0
}
},
methods: {
// 子组件事件
incrementCounter: function () {
this.counter += 1
// 释放父组件事件
this.$emit('increment')
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
// 父组件事件
incrementTotal: function () {
this.total += 1
}
}
})
使用v-model更新父组件数据,请看示例:
<div id="counter-event-example">
<p>{ { total } }</p>
<button-counter v-model="total"></button-counter>
<button-counter v-model="total"></button-counter>
</div>
Vue.component('button-counter', {
template: '<button @click="incrementCounter">{ { counter } }</button>',
data: function () {
return {
counter: 0
}
},
methods: {
// 子组件事件
incrementCounter: function () {
this.counter += 1
// 更新父组件数据
this.$emit('input',this.counter)
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
}
})
非父子组件通信
兄弟组件通信使用一个空的Vue实例作为中央事件总线(bus),类似中介的模式。组件A发送到bus,bus在发送组件B。可以使用vuex插件管理复杂组件关系。
Slot 插槽
插槽能够混合父组件的内容和子组件的模板,插槽的作用域在父组件。
假定 my-component
组件有如下模板:
<div>
<h2>我是子组件的标题</h2>
<slot>
只有在没有要分发的内容时才会显示。
</slot>
</div>
父组件模板:
<div>
<h1>我是父组件的标题</h1>
<my-component>
<p>这是一些初始内容</p>
<p>这是更多的初始内容</p>
</my-component>
</div>
渲染结果:
<div>
<h1>我是父组件的标题</h1>
<div>
<h2>我是子组件的标题</h2>
<p>这是一些初始内容</p>
<p>这是更多的初始内容</p>
</div>
</div>
slot还可以具名,每个组件能够添加多个slot。
插槽的主要功能是能够支持父子组件的模板进行混合,减少子组件内的模板的复杂性。
组件的一些高级用法
递归组件
子组件调用本身,实现类似省市县级连选择器和树形菜单控件
内联模板
组件使用 inline-template 特性时,组件会把他的内容当作模板,而不分发(slot)。
内联模板子组件下可以直接渲染父组件的数据。
动态组件
动态的挂载不同组件,例如页面中不同组件时使用。
<component :is="currentView">
<!-- 组件在 vm.currentview 变化时改变! -->
</component>
异步组件
只在组件需要渲染时触发工厂函数,并且把结果缓存起来,用于后面的再次渲染。
实际使用中在注册时采用异步即可,例如:
new Vu e({
// ...
components: {
'my-component': () => import('./my-async-component')
}
})