9.Vue.js前端框架:组件

1、什么是组件

在使用 Vue 进行前端项目开发过程中,组件的使用最为广泛。然而,什么是组件呢?组件,是 Vue.js 最强大的功能之一。通过开发组件可以封装可复用的代码,将封装好的代码注册成标签,实现扩展 HTML 元素的功能。

2、注册组件

在使用组件之前需要将组件注册到应用中,Vue.js 提供了两种注册方式,局部注册组件和全局注册组件。

2.1 注册全局组件

全局组件可以在所有实例中使用,注册一个全局组件的语法格式:

Vue.component (tagName,option)

语法格式中的两个参数含义分别为:

  • tagName:表示定义的组件名称。对于组件的命名,建议遵循 W3C 规范中的自定义组件命名方式,即字母全部小写并包含一个连字符“-”。
  • option:该参数可以是应用 Vue.extend() 方法创建的一个组件构造器,还可以是组件的选项对象。因为组件是可复用的 Vue 实例,所有它们与一个 Vue 实例一样接收相同选项(el 选项除外),例如,data、computed、watch、methods,以及生命周期钩子等。

全局组件需要在创建的根实例之前注册,这样才能使组件在实例中调用。

在注册组件后,可以在创建的 Vue 实例中以自定义元素的形式进行使用。使用组件的方式如下:

<tagName></tagName>

1、注册一个全局组件的示例代码如下:

<div id="box">
			<my-component></my-component>
		</div>
		   <script type="text/javascript">
		   //创建组件构造器
		   var myComponent = Vue.extend({
			   template:'<h2>注册全局组件</h2>'
		   });
		   //注册全局组件
		   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:'<h2>注册全局组件</h2>'
		   })
		   //创建根实例
		   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:'<div>\
			   <h2>注册全局组件</h2>\
			   <span>全局组件在所有实例中都可用</span>\
			   </div>'
		   })
		   //创建根实例
		   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:'<button v-on:click="count++">单击{{count}}次</button>'
		   })
		   //创建根实例
		   var vm =new Vue({
			   el :'#box'
		   })
		   </script>

运行结果如下图所示:
在这里插入图片描述

2.2 注册局部组件

1、使用 Vue 实例中的 component 选项可以注册一个局部组件。对于 component 对象中的每个属性而言,其属性名就是定义组件的名称,其属性值就是这个组件的选项对象。局部组件只能在当前实例中使用。简单示例如下:

<div id="box">
			<my-component></my-component>
		</div>
		   <script type="text/javascript">
		   var Child ={
			   template :'<h2> 注册局部组件</h2>'
		   }
		   //创建根实例
		   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 :'<h2> 子组件</h2>'
		   }
		   var Parent ={
			   template :'<div>\
			   <h2>父组件</h2>\
			   <child-component></child-component>\
			   </div>',
			   components:{
				   'child-component' : Child
			   }
		   }
		   //创建根实例
		   var vm =new Vue({
			   el :'#box',
			   components:{
				   'parent-component':Parent //注册局部组件
			   }
		   })
		   </script>

运行结果如下图所示:
在这里插入图片描述

3、数据传递

3.1 Prop 是什么

由于组件实例的作用域是孤立的,所以子组件的模板无法直接引用父组件的数据。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:'<p>{{message}}</p>'
		   })
		   //创建根实例
		   var vm =new Vue({
			   el :'#box',
		   })
		   </script>

运行结果如下图所示:
在这里插入图片描述

一个组件默认可以拥有任意数量的 Prop,任何值都可以传递给任何 Prop

3.2 传递动态 Prop

1、通过 v-bind 的方式将父组件中的 data 数据传递给子组件。每当父组件的数据发生变化时子组件也会随之发生变化。示例代码如下所示:

<div id="box">
			<my-component v-bind:boxoffice="boxoffice"></my-component>
			<!--可简写 -->
		    <!--<my-component :boxoffice="boxoffice"></my-component> -->
		</div>
		   <script type="text/javascript">
		   //注册全局组件
		   Vue.component('my-component',{
			   props:['boxoffice'],//传递Prop
			   template:'<p>每天计划跑{{boxoffice}}公里,\
			             加油,未来的你一定会感谢现在努力的自己</p>'
		   })
		   //创建根实例
		   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:'<ol>\
			          <li v-for="item in list">{{item}}</li> </ol>'
		   })
		   //创建根实例
		   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:'<div>\
			        <div>演员:{{actor}}</div>\
					<div>歌手:{{singer}}</div>\
					<div>导演:{{director}}</div>\
					<div>作家:{{writer}}</div>\
					</div>'
		   })
		   //创建根实例
		   var vm =new Vue({
			   el :'#box',
			   data:{
				  type:{
					  actor:'晓茗',
					  singer:'房东的猫',
					  director:'尹涛',
					  writer:'大冰'
				  }
			   }
		   })
		   </script>

运行结果如下图所示:
在这里插入图片描述

4、自定义事件

父组件通过使用 Prop 为子组件传递数据,如果子组件要把数据传递回父组件,需要定义自定义事件来实现。

4.1 自定义事件的监听与触发

1、父组件可以像处理原生 DOM 事件一样通过 v-on 监听子组件实例的自定义事件,而子组件可以通过调用内建的 $emit 方法并传入事件名称来触发自定义事件。
$emit() 方法的语法格式如下:

vm.$emit ( eventName,[...args] )

参数说明如下:

  • 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:'<div>\
			        <button v-on:click="action">放大文本</button>\
					<p>{{text}}</p>\
					</div>',
					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 :'<div class="nav">\
			        <span @click="select(1)" :class="{active: flag===1}">音乐</span>\
					<span @click="select(2)" :class="{active: flag===2}">体育</span>\
					<span @click="select(3)" :class="{active: flag===3}">影视</span>\
					<span @click="select(4)" :class="{active: flag===4}">图片</span>\
					</div>',
					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>

运行结果如下图所示:
在这里插入图片描述

4.2 原生事件绑定到组件

在某个组件的根元素上监听一个原生事件,可以使用 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 :'<div> \
			        <button>单击按钮弹出对话框</button>\
					</div>'
		   })
		   //创建根实例
		   var vm =new Vue({
			   el :'#box',
			   methods:{
				  openDialog : function(){
					  alert("你好,晓茗");
				   }
			   }
			   
		   })
		   </script>

运行结果如下图所示:
在这里插入图片描述

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白_xm

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值