Vue組件應用


  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單文件組件,所以有興趣的同學請移步webpack中文網

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-on指令、實例的$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">),那么你完全可以忽略掉這個限制。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM