当前位置: 移动技术网 > IT编程>开发语言>JavaScript > Vue组件应用

Vue组件应用

2019年12月10日  | 移动技术网IT编程  | 我要评论

  vue的组件是可复用的 vue 实例,且带有一个名字 。我们可以在一个通过 new vue 创建的 vue 根实例中,把这个组件作为自定义元素来使用。因为组件是可复用的 vue 实例,所以它们与 new vue 接收相同的选项,例如 datacomputedwatchmethods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

 

一  创建组件

  vue提供了三种不同的方式来定义组件,分别是:全局组件,私有组件,单文件组件。接下来就让我一一道来。

 

  1,全局组件

  注册全局组件非常简单,也是很常用的一种方式。

1 vue.component('mycom',{
2     template:'<div><p>我是一个全局<span>组件</span></p></div>'
3 });

  vue.component()方法需要两个参数:

    第一个,组件名称;

    第二个,实例(初始化)对象,可以包含所有使用new方式创建vue实例时提供的所有属性,除了el。

  注意:组件的实例对象必须提供一个template属性,用作该组件的html代码模板,且在该模板中有且只能有一个根元素。全局组件的注册必须在创建vue实例之前。

  小技巧:由于在编写js时,一般没有html代码提示,创建组件模板代码会很不方便,所有可以在html文件中使用<template>元素创建模板,然后在组件的template属性中使用id选择器引用该模板。

  注意:<template>元素必须在new vue实例接管的根元素外部。

1 <template id="tem">
2     <div>
3         <p>我是组件内的p</p>
4         <span>我是组件中的span</span>
5     </div>
6 </template>
7 <!-- 在html中 -->
1 vue.component('mycom',{
2     template:'#tem'
3 });
4 //在组件中

  

  2,私有组件

  全局创建的组件在所有vue实例中均可以使用,有时候这并不符合我们的需求。你可以通过以下方式定义vue实例的私有组件,这些组件只能在该vue实例根元素内部使用。

1 var vm = new vue({
2     el:'#app',
3     components:{
4         mycom:{
5             template:'#tem'
6         }
7     }
8 });

  通过vue实例的components属性可以定义私有组件,该属性绑定一个对象,对象的属性名是组件名,属性值是组件实例对象。

  

  3,单文件组件

  vue的单文件组件是一个以.vue为后缀名的文件。由于html和javascrip不能识别.vue文件,所以不能直接使用这种方式的组件,必须配合webpack或vue-cli工具才能正确解析.vue文件。这里的重点是vue单文件组件,所以有兴趣的同学请移步。

1 <tempalte>
2     //html模板
3 </template>
4 <script>
5     //js代码
6 </script>
7 <style>
8     //css代码
9 </style>

  .vue文件的名称就是组件的名称,其结构非常简单、清晰:

    <template>标签是组件的html模板;

    <script>标签是逻辑代码;

    <style>标签中是样式代码。

 

二  组件的使用

  不管以哪种方式创建vue组件,我们最终的目的是在html页面中展示出来。本节将详细介绍vue组件使用方式。

 

  1,组件标签

  要把我们创建的vue组件添加到页面中去,只需要把组件名当做标签来使用即可。

1 vue.component('mycom',{
2     template:"#tem"
3 });
4 var vm = new vue({
5     el:"#app"
6 });
7 //js部分
1 <div id="app">
2     <my-com></my-com>
3 </div>
4 <!-- html部分 -->

  小技巧:注册组件时,建议使用全小写形式命名,因为html标签要求使用小写字母。如果你一定要遵守小驼峰命名规则,那么你应该在使用组件时用“-”短横线把单词分隔开。

  

  2,组件复用

  vue的组件可以重复使用。

1 <div id="app">
2     <my-com></my-com>
3     <my-com></my-com>
4     <my-com></my-com>
5 </div>

  当然,全局组件可以在任何地方使用,而私有组件只能在实例接管元素内部使用。

  组件不仅可以简单的重复使用,还可以嵌套。

 1 var vm = new vue({
 2     el:'#app',
 3     compontents:{
 4         mycom1:{
 5             template:'<div>组件一  <mycom2></mycom2></div>'
 6         },
 7         mycom2:{
 8             template:'<div>组件二</div>'
 9         }
10     }
11 });

  

  3,另一种使用方式

1 var mycom = {
2     tempalte:'<div id="app2">hello</div>'
3 };
4 var vm = new vue({
5     el:'#app',
6     render:function(createel){
7         return createel(mycom);
8     }
9 });

  使用render方式渲染组件:给vue实例添加render属性,该属性值是一个接收一个方法作为参数的函数。参数用于创建vue组件,return该组件将替代vue实例接管的#app元素。最终的表现是:页面上将不再出现#app的div,取而代之的是#app2的div。

  这种方式一般配合单文件组件使用,如果要渲染多个组件,只需要创建多个vue实例即可。

 

三  数据传递(通信)

 

  1,props传递数据(父组件 --> 子组件)

  通过在子组件绑定props属性,实现父组件向子组件传递数据。props属性值是一个数组,数组元素被定义用来接收父组件传递来的数据,然后通过v-bind指令指定数组元素接收哪些数据。子组件通过访问props数组元素就可以访问到父组件传递过来的数据了,就如同访问data里面的值。

 

1 <div id="app">
2     <mycom :fromfathermsg="tosonmsg"></mycom>
3 </div>
4 <!-- html部分 -->
 1 vue.component({
 2     template:"<div>{{fromfathermsg}}</div>",
 3     props:["fromfathermsg"]
 4 });
 5 var vm = new vue({
 6     el:'#app',
 7     data:{
 8         tosonmsg:'这是给子组件的数据'
 9     }
10 });
11 //js部分

  通过上面的例子,我们可以将这个过程简单的分为三步:

    第一步,在子组件上添加一个数组属性props,在数组中定义用来接收数据的变量(以字符串形式存储);

    第二步,使用子组件时通过v-bind指令,绑定预先定义的接收变量和父组件将要传递过来的值;

    第三步,在子组件中,如同访问data中的数据一样,访问props数组元素接收到的数据。

  

  2,$emit传递方法(父组件 --> 子组件)

  父组件向子组件传递方法,是通过自定义事件来实现的。

  监听(同时注册)自定义事件有两种方式:组件上使用v-bind、实例的$on()。这里我们将使用第一种方式来做演示。

  子组件通过实例的$emit()方法触发自定义事件,这里的事件名将成为$emit()方法的第一个参数。

1 <div id="app">
2     <mycom @fromfatherfun="tosonfun"></mycom>
3 </div>
4 <!-- html部分 -->
 1 vue.component({
 2     template:"<div><button @click="myfun">点击执行来自父组件的方法</button></div>",
 3     methods:{
 4         myfun:function(){
 5             this.$emit('fromfatherfun');
 6         }
 7     }
 8 });
 9 var vm = new vue({
10     el:'#app',
11     methods:{
12         tosonfun(){
13         console.log( "这是给子组件的方法");
14     },
15 });
16 //js部分

  注意:和传递数据一样,子组件不能直接使用父组件的方法。子组件需要通过实例的$emit()方法间接执行来自父组件的方法。

  这一过程也可以分为三步:

    第一步,使用子组件时,通过v-on指令自定义一个事件;

    第二步,绑定自定义事件和父组件需要传递的方法(指定回调函数);

    第三步,通过子组件的$emit()方法(通过实参指定需要触发的自定义事件)触发父组件的方法执行;

  

  3,子组件抛出值(子组件 --> 父组件)

  子组件在通过$emit()触发自定义事件时,可以同时利用方法的第二个参数,向外抛出一个值。回调函数(上面父组件传递下来的方法)需要定义一个形参来接收这个子组件抛出的值。

 1 //接上面的例子
 2 vue.component({
 3     template:"<div><button @click="myfun">点击执行来自父组件的方法</button></div>",
 4     data(){
 5         return {name:'ren'};
 6     },
 7     methods:{
 8         myfun:function(){
 9             this.$emit('fromfatherfun',this.name);
10         }
11     }
12 });
13 var vm = new vue({
14     el:'#app',
15     data:{
16         namefromson:null
17     }
18     methods:{
19         tosonfun(data){
20         this.namefromson = data;
21     },
22 });

  子组件抛出一个值的原理和父组件给子组件传递方法原理是一样的,只不过是不同的用法而已。虽然有点绕,但有用哦。

  

  4,获取子组件的引用

  在使用子组件时,通过绑定ref属性,父组件可以通过vue实例的$refs属性拿到子组件的引用,然后就可以直接访问子组件的属性或方法了。

1 <div id="app">
2  <mycom ref="soncom"></mycom>
3   <button @click="printmsgfromson">点击打印子组件的信息</button>
4 </div>
5 <!-- html部分 -->
 1 vue.component('mycom',{
 2     data:function(){return {name:'ren'}}
 3 });
 4 
 5 var vm = new vue({
 6     el:'#app',
 7     methods:{
 8         printmsgfromson:function(){
 9             console.log(this.$refs.soncom.name);
10         }
11     }
12 });
13 //js部分

  小技巧:ref属性不仅可以用在组件上,也可以用在其他标准html标签上,这样vue实例就可以获取到原生的dom对象了。

  注意:即使子组件是vue实例的私有组件,实例也不能直接使用组件的相关数据,还是需要通过$refs等属性来间接访问。

 

  5,兄弟组件间传值

   兄弟组件间实现通信也是采用自定义事件的形式。不过,这一般需要一个空的vue实例作为中介,配合使用$on()和$emit()实现兄弟组件间的传值。

 1 <div id="app">
 2     <com1></com1>
 3     <com2></com2>
 4 </div>
 5 <template id="com1">
 6   <div>
 7     <p>com1组件:{{name}}</p>
 8     <button @click="send">将数据发送给com2</button>
 9   </div>
10 </template>
11 <template id="com2">
12   <div>
13     <p>com2组件:{{name}}</p>
14   </div>
15 </template>
16 <!-- html部分 -->

 

 1 var event = new vue();
 2 var vm = new vue({
 3     el:'#app',
 4     components:{
 5         com1:{
 6             template:'#com1',
 7             data(){
 8                 return{name:'ren'};
 9             },
10             methods:{
11                 send(){
12                     event.$emit('sendmsg',this.name);
13                 }
14             }
15         },
16         com2:{
17             template:'#com2',
18             data(){
19                 return {name:null};
20             },
21             created(){//因为不知道什么时候会被触发,所以一般选择在生命周期钩子中监听
22                 event.$on('sendmsg',name => {this.name = name;})
23                 //这里需要使用箭头函数,使其内部的this指向com2
24             }
25         }
26     }
27 });
28 //js部分

 

 

四  其他事项

 

  1,单独的data

  经过上面的学习,你可能已经发现了一个问题:组件中的data属性是一个函数返回的对象。

1 vue.component("mycom",{
2     template:"",
3     data(){
4         return { //some code };
5     }
6 });
7 //这是es6的写法,等同于data:function(){return {some code};}

  由于data属性绑定的是一个对象,而对象是一个引用类型,为了保证为每个组件维护一份独立的数据,组件的data属性必须是一个函数。

  

  2,插槽<slot>

  当你读到这里时,你可能会有一个疑问:既然我们可以用标签形式使用vue组件,那么是否可以在开始标签和结束标签之间填些内容呢?如果可以的话,该如何做呢?vue的答案是肯定的。

  首先请看下面的例子:

1 <div id="app">
2     <com>我是插槽内容</com>
3 </div>
4 <!-- html部分 -->
1 vue.compenent('com',{
2     template:'<div><p>我是组件</p><slot>我是默认值<slot></div>'
3 });
4 var vm = new vue({
5     el:'#app'
6 });
7 //js部分

  "我是插槽内容"将替换com组件中<slot>元素。

  注意:如果在使用子组件时没有提供插槽值,那么<slot>元素中的默认值将会生效,前提是你已经定义了这些值。

  上面的例子中,组件最终渲染的html结构如下:

1 <div>
2     <p>我是组件</p>
3     我是插槽内容
4 </div>

  注意:插槽的内容不仅可以是文本内容,还可以是html代码,甚至另一个组件。

  如果你需要在一个组件中定义多个插槽,那么你应该需要用到<slot>元素的name属性,来指定每个插槽应该拥有怎么样的模板。

 1 <div>
 2     <com>
 3         <template v-slot:"header">
 4             <!-- 单独的html模板 -->
 5         </template>
 6         <div><p>我是默认的模板</p></div>
 7         <template v-slot:"footer">
 8             <!-- 单独的html模板 -->
 9         </template>
10     </com>
11 </div>
12 <!-- html部分 -->
1 vue.component('com',{
2     tempalte:'<div><slot name="header"></slot><slot></slot><slot name="footer"></slot></div>'
3 });
4 var vm = new vue({
5     el:'#app'
6 });

  具名的插槽需要在使用组件时,用<template>元素单独定义模板,并通过v-slot指令以参数的形式指定:“我是xxx插槽的模板”。

  其他所有没有包裹在<template>元素内的模板,将自动归为匿名的<slot>元素下面。

 

  

  3,特殊的嵌套元素

  有些 html 元素,诸如 <ul><ol><table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li><tr> 和 <option>,只能出现在其它某些特定的元素内部。要怎样才能在这些元素中正确的渲染组件呢?幸好,vue提供了is特性:

1 <table>
2   <tr is="mycom"></tr>
3 </table>

  注意:如果你使用字符串定义组件模板(例如:template: '...')、或者单文件组件(.vue)、或者<script>标签(<script type="text/x-template">),那么你完全可以忽略掉这个限制。

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网