在使用 Vue 进行前端项目开发过程中,组件的使用最为广泛。然而,什么是组件呢?组件,是 Vue.js 最强大的功能之一。通过开发组件可以封装可复用的代码,将封装好的代码注册成标签,实现扩展 HTML 元素的功能。
在使用组件之前需要将组件注册到应用中,Vue.js 提供了两种注册方式,局部注册组件和全局注册组件。
全局组件可以在所有实例中使用,注册一个全局组件的语法格式:
Vue.component (tagName,option)
语法格式中的两个参数含义分别为:
全局组件需要在创建的根实例之前注册,这样才能使组件在实例中调用。
在注册组件后,可以在创建的 Vue 实例中以自定义元素的形式进行使用。使用组件的方式如下:
<tagName>tagName>
1、注册一个全局组件的示例代码如下:
<div id="box">
<my-component>my-component>
div>
<script type="text/javascript">
//创建组件构造器
var myComponent = Vue.extend({
template:'注册全局组件
'
});
//注册全局组件
Vue.component('my-component',myComponent)
//创建根实例
var vm =new Vue({
el :'#box'
})
script>
运行结果如下图所示:
2、上述代码使用了组件构造器的方式。在注册全局组件时,还可以在注册的时候直接传入选项对象而不是构造器。示例代码如下所示:
<div id="box">
<my-component>my-component>
div>
<script type="text/javascript">
//注册全局组件
Vue.component('my-component',{
template:'注册全局组件
'
})
//创建根实例
var vm =new Vue({
el :'#box'
})
script>
注意:为了使代码更简化,建议在注册组件的时候采用直接传入选项对象的方式,形如第二种创建组件的方式。
3、如果组件的模板里面有多个元素,可以将模板的内容包含在一个父元素内,示例代码如下所示:
<div id="box">
<my-component>my-component>
div>
<script type="text/javascript">
//注册全局组件
Vue.component('my-component',{
template:'\
注册全局组件
\
全局组件在所有实例中都可用\
'
})
//创建根实例
var vm =new Vue({
el :'#box'
})
script>
运行结果如下图所示:
4、组件选项对象中的 data 和 Vue 实例对象中的 data 的赋值是不同的。一个组件的 data 选项必须是一个函数,而不是一个对象。示例代码如下:
<div id="box">
<button-count>button-count>
<button-count>button-count>
<button-count>button-count>
div>
<script type="text/javascript">
//注册全局组件
Vue.component('button-count',{
data:function(){
return {
count :0
}
},
template:''
})
//创建根实例
var vm =new Vue({
el :'#box'
})
script>
1、使用 Vue 实例中的 component 选项可以注册一个局部组件。对于 component 对象中的每个属性而言,其属性名就是定义组件的名称,其属性值就是这个组件的选项对象。局部组件只能在当前实例中使用。简单示例如下:
<div id="box">
<my-component>my-component>
div>
<script type="text/javascript">
var Child ={
template :' 注册局部组件
'
}
//创建根实例
var vm =new Vue({
el :'#box',
components:{
'my-component':Child //注册局部组件
}
})
script>
运行结果如下图所示:
2、局部注册的组件只能在其父组件中使用,而无法在其他组件中使用。例如,有两个局部组件 A 和 B,如果希望 A 在 B 中可用,则需要将 A 定义在 B 的 components 选项中。示例代码如下:
<div id="box">
<parent-component>parent-component>
div>
<script type="text/javascript">
var Child ={
template :' 子组件
'
}
var Parent ={
template :'\
父组件
\
\
',
components:{
'child-component' : Child
}
}
//创建根实例
var vm =new Vue({
el :'#box',
components:{
'parent-component':Parent //注册局部组件
}
})
script>
由于组件实例的作用域是孤立的,所以子组件的模板无法直接引用父组件的数据。Prop 的出现便是实现父子组件之间数据的传递。
Prop 是父组件用来传递数据的一个自定义属性,该属性需要定义在组件选项对象的 props 选项中。通过 props 选项中定义的属性可以将父组件的数据传递给子组件,而子组件需要显式地用 props 选项来声明 Prop。示例代码如下所示:
<div id="box">
<my-component message="因为热爱,所以奔赴">my-component>
div>
<script type="text/javascript">
//注册全局组件
Vue.component('my-component',{
props:['message'],//传递Prop
template:'{
{message}}
'
})
//创建根实例
var vm =new Vue({
el :'#box',
})
script>
一个组件默认可以拥有任意数量的 Prop,任何值都可以传递给任何 Prop
1、通过 v-bind 的方式将父组件中的 data 数据传递给子组件。每当父组件的数据发生变化时子组件也会随之发生变化。示例代码如下所示:
<div id="box">
<my-component v-bind:boxoffice="boxoffice">my-component>
div>
<script type="text/javascript">
//注册全局组件
Vue.component('my-component',{
props:['boxoffice'],//传递Prop
template:'每天计划跑{
{boxoffice}}公里,\
加油,未来的你一定会感谢现在努力的自己
'
})
//创建根实例
var vm =new Vue({
el :'#box',
data:{
boxoffice:4.5
}
})
script>
当 根实例中的 boxoffice 值发生改变时,组件中的值也会随之改变,运行结果如下图所示:
2、使用 Prop 传递的数据可以是数值和字符串类型外,还可以是数组或对象类型。传递数组类型数据的示例代码如下所示:
<div id="box">
<my-item :list="type">my-item>
div>
<script type="text/javascript">
//注册全局组件
Vue.component('my-item',{
props:['list'],//传递数组类型Prop
template:'\
- {
{item}}
'
})
//创建根实例
var vm =new Vue({
el :'#box',
data:{
type :['演员','歌手','导演','作家']
}
})
script>
注意:如果 Prop 传递的是一个对象或数组,那么它是按引用传递的。在子组件内修改这个对象或数组本身将会影响父组件的状态。
3、在传递对象类型的数据时,如果想要将一个对象的所有属性都作为 Prop 传入,可以使用不带参数的 v-bind。示例代码如下所示:
div id="box">
<my-item v-bind="type">my-item>
div>
<script type="text/javascript">
//注册全局组件
Vue.component('my-item',{
props:['actor','singer','director','writer'],//传递数组类型Prop
template:'\
演员:{
{actor}}\
歌手:{
{singer}}\
导演:{
{director}}\
作家:{
{writer}}\
'
})
//创建根实例
var vm =new Vue({
el :'#box',
data:{
type:{
actor:'晓茗',
singer:'房东的猫',
director:'尹涛',
writer:'大冰'
}
}
})
script>
父组件通过使用 Prop 为子组件传递数据,如果子组件要把数据传递回父组件,需要定义自定义事件来实现。
1、父组件可以像处理原生 DOM 事件一样通过 v-on 监听子组件实例的自定义事件,而子组件可以通过调用内建的 $emit 方法并传入事件名称来触发自定义事件。
$emit() 方法的语法格式如下:
vm.$emit ( eventName,[...args] )
参数说明如下:
<div id="box">
<div v-bind:style="{
fontSize: fontSize+'px'}">
<my-font v-bind:text="text" v-on:enlarge="fontSize +=2">my-font>
div>
div>
<script type="text/javascript">
//注册全局组件
Vue.component('my-font',{
props:['text'],
template:'\
\
{
{text}}
\
',
methods:{
action:function(){
this.$emit('enlarge');//触发自定义enlarge事件
}
}
})
//创建根实例
var vm =new Vue({
el :'#box',
data:{
text:'世界那么大,我想去看看',
fontSize:17
}
})
script>
运行结果如下图所示:
2、在父组件监听自定义事件时,如果事件处理程序是一个方法,通过 $emit() 方法传递的参数将会作为第 1 个参数传入该方法中,示例代码如下所示:
<div id="box">
<my-menu @select-item="onSelectItem" :flag="flag">my-menu>
div>
<script type="text/javascript">
//注册全局组件
Vue.component('my-menu',{
props:['flag'],
template :' ',
methods:{
select (value){
this.$emit('select-item',value) //触发自定义事件并传递参数
}
}
})
//创建根实例
var vm =new Vue({
el :'#box',
data:{
flag :1
},
methods:{
onSelectItem:function(value){
this.flag=value
}
}
})
script>
在某个组件的根元素上监听一个原生事件,可以使用 v-on 的 .native 修饰符。例如,在组件的根元素上监听 click 事件,当单击组件时弹出“你好,晓茗”的对话框,示例代码如下所示:
<div id="box">
<my-component v-on:click.native="openDialog">my-component>
div>
<script type="text/javascript">
//注册全局组件
Vue.component('my-component',{
template :' \
\
'
})
//创建根实例
var vm =new Vue({
el :'#box',
methods:{
openDialog : function(){
alert("你好,晓茗");
}
}
})
script>