Vue 最强大的功能之一就是组件(Component)!
组件可以扩展 HTML 元素,封装可重用的代码,方便开发者更灵活的构建大型的前端项目。
一、定义全局组件
全局组件定义格式:Vue.component(tagName, options),下面的程序我们注册一个全局组件,并使用<helloWorld></helloWorld>的标签进行引用:
<template>
<div id="hello">
<helloWorld></helloWorld>
</div>
</template>
<script>
import Vue from "vue";
Vue.component('helloWorld',{
template:'<h2>自定义全局组件:helloWorld</h2>'
})
export default {
name: 'hello'
}
</script>
二、定义局部组件
我们也可以在实例中注册局部组件,只能在实例中通过components:{ }属性注入使用:
<template>
<div id="hello">
<helloWorld></helloWorld>
</div>
</template>
<script>
var Child = {
template: '<h3>自定义局部组件:helloWorld</h3>'
}
export default {
name: 'hello',
components: {
'helloWorld': Child
}
}
</script>
三、Prop属性使用
1、常规使用方式:
prop 是父组件用来传递数据的一个自定义属性,子组件需要显式地用 props 选项声明 “prop”。下面的实例中,我们在组件内部使用 props: [‘msg’] 来引入msg变量,并在组件内部使用:
<template>
<div id="hello">
<helloWorld msg="hello World 12345!!"></helloWorld>
<helloWorld2></helloWorld2>
</div>
</template>
<script>
import Vue from "vue";
Vue.component('helloWorld',{
props: ['msg'],
template:'<h2>自定义全局组件:{{msg}}</h2>'
})
export default {
name: 'hello'
}
</script>
2、动态绑定方式:
除了上面的props属性使用方式,我们还可以将props属性绑定到一个动态变量中,下面程序定义一个hello_World的变量将其绑定到props:msg属性中,并定义了一个表单input元素,用于手动修改输入的数据:
<template>
<div id="hello">
<input v-model="hello_World">
<br>
<helloWorld v-bind:msg="hello_World"></helloWorld>
</div>
</template>
<script>
import Vue from "vue";
Vue.component('helloWorld',{
props: ['msg'],
template:'<h2>自定义全局组件:{{msg}}</h2>'
})
export default {
name: 'hello',
data(){
return{
hello_World:'wx:594218572'
}
}
}
</script>
运行效果:
3、数组属性绑定:
在这个实例中,我们结合v-for和组件实现数组方式的模板调用:
<template>
<div id="hello">
<helloWorld v-for = 'item in books' v-bind:msg = "item"></helloWorld>
</div>
</template>
<script>
import Vue from "vue";
Vue.component('helloWorld',{
props: ['msg'],
template:'<h2>自定义全局组件:{{msg.book}}</h2>'
})
export default {
name: 'hello',
data(){
return{
books:[
{ book: 'Java编程思想' },
{ book: 'Vue教程学习' },
{ book: 'JavaScript高手' }
]
}
}
}
</script>
另外,prop 属于单向绑定:父组件的属性变化时,会传递给子组件,反之不会。
4、Prop验证:
组件可以指定 props 的验证要求,下面我们对msg进行Number类型验证:
<template>
<div id="hello">
<helloWorld v-bind:msg="hello_World"></helloWorld>
</div>
</template>
<script>
import Vue from "vue";
Vue.component('helloWorld',{
props: {
msg:Number
},
template:'<h2>自定义全局组件:{{msg}}</h2>'
})
export default {
name: 'hello',
data(){
return{
hello_World:'wx:594218572'
}
}
}
</script>
由于 wx:594218572 不是Number类型,所以控制台抛出一个异常信息:
此外,还可以进行以下的方式验证:
// 多个可能的类型:
msg: [Number,String],
// 必填内容校验 + 默认值:
msg2: {
type: Number,
required: true,
default: 100
},
//自定义验证:
msg3: {
validator: function (value) {
if(value == '0')
return false;
return true;
}
}
type 可以是以下类型的原生构造器:
String
Number
Boolean
Array
Object
Date
Function
Symbol
(type 也可以使用 instanceof 检测一个自定义构造器)
四、自定义事件
由于prop 属于单向绑定,如果我们需要子组件要把数据传递回去,需要使用自定义事件,直接使用 v-on 绑定我们自定义的事件, 子组件使用 $emit 触发父组件的自定义事件,以下实例子组件和外部完全解耦,它只是触发一个父组件关心的内部事件:
<template>
<div id="hello">
<h1>{{total}}</h1>
<helloWorld v-on:addition="hello_World"></helloWorld>
</div>
</template>
<script>
import Vue from "vue";
Vue.component('helloWorld',{
template: '<button v-on:click="counter">{{ count }}</button>',
data: function () {
return {
count : 0
}
},
methods:{
counter:function () {
this.count += 1
this.$emit('addition')
}
}
})
export default {
name: 'hello',
data(){
return{
total:0
}
},
methods:{
hello_World:function () {
this.total += 1;
}
}
}
</script>
以上的程序执行顺序:
1、执行子组件 v-on:click="counter" 的逻辑;
2、执行子组件内 counter:function 的函数,然后通过this.$emit('addition')触发父组件中的 v-on:addition 自定义事件;
3、执行父组件自定义事件 v-on:addition 所指向的 hello_World: function函数,进行加法计算;
(父、子组件内的加法是两个独立函数)
另外,如果要在组件的根元素上监听原生事件,使用 .native 修饰 v-on :
<helloWorld v-on:click.native="doSomeThing"></helloWorld>
END.