VUE 自定義組件之間的相互通信


一、自定義組件

1、全局自定義組件

我們在var vm = new Vue({});的上面並列寫上Vue.component('自定義組件名',{組件對象});來完成全局自定義組件的聲明。示例代碼如下:

<script> window.onload = function(){ Vue.component('my-aaa',{ template:'<h3>全局自定義組件</h3>' }); var vm = new Vue({ el:'#box' }); } </script> <div id="box"> <my-aaa></my-aaa> </div>

即我們在該自定義組件的組件對象的template屬性值當中設置該組件標簽即將被替換成的html標簽字符串。即我們使用<my-aaa></my-aaa>,則相當於是<h3>全局自定義組件</h3>

2、局部自定義組件

我們在var vm = new Vue({});這個實例對象內部的屬性components:{'自定義組件名':{該組件對象}}的對象內部聲明局部自定義組件。 示例代碼如下所示:

<script> window.onload = function(){ var vm = new Vue({ el:'#box', components:{ 'my-bbb':{ template:'<h3>局部自定義組件</h3>' } } }); }; </script> <div id="box"> <my-bbb></my-bbb> </div> 

全局自定義組件與局部自定義組件的用法大致都相似,下面主要以全局自定義組件為例來進行詳細的說明。

3、自定義組件的數據屬性

我們可以在自定義組件的組件對象的data屬性當中放置該組件的數據屬性。但data必須為函數的形式,並且該函數必須返回一個對象,我們在該返回的對象當中放置該組件的數據。示例代碼如下所示:

<script> window.onload = function(){ Vue.component('my-aaa',{ template:'<h3>{{msg}}</h3>', data:function(){ return { msg:'哈哈!' }; } }); var vm = new Vue({ el:'#box' }); }; </script> <div id="box"> <my-aaa></my-aaa> </div> 

4、自定義組件的事件方法

我們可以在自定義組件對象的methods當中定義該組件的事件方法,示例代碼如下所示:

<script> window.onload = function(){ Vue.component('my-aaa',{ template:'<h3 @click="change">{{msg}}</h3>', data:function(){ return { msg:'哈哈!' }; }, methods:{ change:function(){ this.msg = 'change'; } } }); var vm = new Vue({ el:'#box' }); }; </script> <div id="box"> <my-aaa></my-aaa> </div>

5、template屬性值配合模板標簽使用

如果我們自定義組件對象的template屬性值當中的html標簽比較多時,可以配合模板標簽一起使用,把這些成堆的標簽單獨放在一起。示例代碼如下所示:

 <script> window.onload = function(){ Vue.component('my-aaa',{ template:'#ccc', data:function(){ return { msg:'哈哈!', arr:['apple','banana','pear','tomato'] }; }, methods:{ change:function(){ this.msg = 'change'; } } }); var vm = new Vue({ el:'#box' }); }; </script> <div id="box"> <my-aaa></my-aaa> </div> <template id="ccc"> <div> <h3 @click="change">{{msg}}</h3> <ul> <li v-for="(val,index) in arr"> {{index}}----{{val}} </li> </ul> </div> </template> 

顯示結果如下所示,當點'哈哈!'時,會變為change

vue1.x的版本過渡到vue2.0的版本的變化之一為,每個組件模板不再支持片段代碼,即在vue2.0當中的組件模板必須有一個根元素來包裹住所有的代碼。即當上述代碼更改為

 <template id="ccc"> <h3 @click="change">{{msg}}</h3> <ul> <li v-for="(val,index) in arr"> {{index}}----{{val}} </li> </ul> </template>

則會報錯component template should contain exactly one root element.

6、動態組件

我們在頁面上放置一個固定名稱的組件標簽作為動態組件,如<component :is="a"></component>,其中a來自於vue實例對象的data屬性,通過給a賦予不同的自定義組件名,可以控制該動態組件當前的狀態。示例代碼如下所示:

<script> window.onload = function(){ var vm = new Vue({ el:'#box', data:{ a:'my-aaa' }, components:{ 'my-aaa':{ template:'<h3>我是組件aaa</h3>' }, 'my-bbb':{ template:'<h3>我是組件bbb</h3>' } } }); }; </script> <div id="box"> <button @click="a='my-bbb'">變為組件bbb</button> <button @click="a='my-aaa'">變為組件aaa</button> <component :is="a"></component> </div> 

當頁面完成加載之后,a的初始值為'my-aaa',故此時頁面上的動態組件代表<my-aaa></my-aaa>,當我們點擊變為組件bbb按鈕時,a被賦值,此時頁面的動態組件變為<my-bbb></my-bbb>。但當點擊變為組件aaa按鈕時,a又被重新賦值,此時頁面上的動態組件變回<my-aaa></my-aaa>

7、<slot>標簽的使用

slot為位置、槽口的意思,作用為占位置。當自定義組件當中有一些特定的布局,不想被該組件當中的template的代碼完全覆蓋時,可以采用slot這個標簽,該標簽可以用來向組件內部插入一些內容,即我們在定義組件的時候留幾個口子,由用戶來決定插入的內容。單個插槽的示例代碼如下所示:

<script> window.onload = function(){ Vue.component('my-aaa',{ template:'#ccc' }); var vm = new Vue({ el:'#box' }); }; </script> <div id="box"> <my-aaa> <ul> <li>aaaa</li> <li>bbbb</li> </ul> </my-aaa> </div> <template id="ccc"> <div> <slot>只有在沒有要分發的內容時才會顯示</slot> <h3>自定義組件aaa</h3> </div> </template> 

當我們在使用<my-aaa></my-aaa>組件標簽時,內部沒有其他內容,則slot標簽對當中的文字內容會正常顯示,但當該組件標簽對當中有html代碼時,則slot標簽對當中的文字部分不會顯示,並且在默認情況下,一對slot標簽對即代表該組件標簽對當中全部的html代碼段。

vue2.0當中,重名的插槽被移除,即同一模板當中重名的slot已經被棄用,當一個插槽已經被渲染過了,那么就不能在同一模板的其他地方被再次渲染,如果要在不同位置渲染同一內容,可以用prop來傳遞。

具名插槽的示例代碼如下所示:

<script> window.onload = function(){ Vue.component('my-aaa',{ template:'#ccc' }); var vm = new Vue({ el:'#box' }); }; </script> <div id="box"> <my-aaa> <ul slot="ul-slot1"> <li>aaaa</li> <li>bbbb</li> </ul> <ul slot="ul-slot2"> <li>cccc</li> <li>dddd</li> </ul> </my-aaa> </div> <template id="ccc"> <div> <slot name="ul-slot2"></slot> <h3>自定義組件aaa</h3> <slot name="ul-slot1"></slot> </div> </template> 

二、組件間的通信

1、父子組件

我們可以在自定義組件對象當中的components屬性當中定義該組件對應的子組件。示例代碼如下所示:

<script> window.onload = function(){ Vue.component('my-aaa',{ template:'#ccc', components:{ 'my-bbb':{ template:'<h4>{{msg}}</h4>', data:function(){ return { msg:'子組件bbb' }; } } } }); var vm = new Vue({ el:'#box' }); }; </script> <div id="box"> <my-aaa></my-aaa> </div> <template id="ccc"> <div> <h3>自定義組件aaa</h3> <my-bbb></my-bbb> </div> </template> 

2、子組件獲取其父組件的數據

在默認情況下,子組件是無法訪問到其父組件當中的數據的。如果希望子組件能獲取到父組件的data數據,使其能在子組件的templatehtml代碼當中直接使用。則我們可以在給子組件的標簽綁定上一個屬性m(該屬性名可以任取),將父級的數據掛載到子組件的m屬性值上。然后我們在子組件對應的組件對象當中使用props:['m']來得到該m屬性值,之后的可以把m當作是來自於子組件對象當中的data,即在子組件的template當中可以用{{m}}來獲取,在methods當中可以用this.m來進行獲取。示例代碼如下所示:

<script> window.onload = function(){ Vue.component('my-aaa',{ template:'#ccc', data:function(){ return { msg1:'嘻嘻!', msg2:'哈哈!', msg3:'呵呵!' }; }, components:{ 'my-bbb':{ template:'#ddd', props:['m1','m2','myM3'] } } }); var vm = new Vue({ el:'#box' }); }; </script> <div id="box"> <my-aaa></my-aaa> </div> <template id="ccc"> <div> <h3>自定義組件aaa</h3> <my-bbb :m1="msg1" :m2="msg2" :my-m3="msg3"></my-bbb> </div> </template> <template id="ddd"> <div> <h1>{{m1}}</h1> <h2>{{m2}}</h2> <h3>{{myM3}}</h3> </div> </template> 

自定義屬性名為my-m3,使用-來進行連接,則我們在props當中一律改為對應的駝峰命名下的myM3

在上述這種方式當中,子組件可以獲取到父組件的數據,但是不允許直接對獲取到的數據進行賦值操作。想要對獲取到的數據進行賦值操作,同時達到更改父組件當中數據的目的,可以采取解決辦法是,我們可以把父組件當中的數據包裹在一個對象當中來進行傳遞。示例代碼如下所示:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="bower_components/vue/dist/vue.js"></script> <script> window.onload = function(){ Vue.component('my-aaa',{ template:'#ccc', data:function(){ return { msg1:{ a:'呵呵!' }, }; }, components:{ 'my-bbb':{ template:'#ddd', props:['m1'], methods:{ change:function(){ this.m1.a = '哈哈!' } } } } }); var vm = new Vue({ el:'#box' }); }; </script> </head> <body> <div id="box"> <my-aaa></my-aaa> </div> <template id="ccc"> <div> <h3>{{msg1.a}}</h3> <my-bbb :m1="msg1"></my-bbb> </div> </template> <template id="ddd"> <div> <button @click="change()">change</button> <h3>{{m1.a}}</h3> </div> </template> </body> </html> 

當點擊按鈕之后,變為:

3、父組件獲取其子組件的數據

父組件想要獲取子組件的數據,一般都是等子組件主動把自己的數據發送給父級。我們可以給子組件的某個dom元素綁定一個事件,該事件函數體為this.$emit('自定義事件名',子組件的數據)。即這個可以觸發子組件身上的事件。示例代碼如下所示:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="bower_components/vue/dist/vue.js"></script> <script> window.onload = function(){ Vue.component('my-aaa',{ template:'#ccc', data:function(){ return { msg1:'父組件的數據' }; }, methods:{ get:function(data){ this.msg1 = data; } }, components:{ 'my-bbb':{ template:'#ddd', data:function(){ return { msg2:'子組件的數據' }; }, methods:{ send:function(){ this.$emit('sendtofahter',this.msg2); } } } } }); var vm = new Vue({ el:'#box' }); }; </script> </head> <body> <div id="box"> <my-aaa></my-aaa> </div> <template id="ccc"> <div> <h3>{{msg1}}</h3> <my-bbb @sendtofahter="get"></my-bbb> </div> </template> <template id="ddd"> <div> <button @click="send()">send-to-father</button> <h3>{{msg2}}</h3> </div> </template> </body> </html> 

當點擊按鈕之后,結果變為:

4、使用單一事件來管理組件間的通信

使用下面介紹的單一事件管理組件間通信可以替代之前介紹的兩種父子組件之間的通信方式,還可以實現任意兩個組件(如兄弟組件)之間的數據通信。

我們可以先在var vm = new Vue({});並列的上方准備一個空的vue實例對象,如var Event = new Vue();。假設我們要實現A組件發送數據給B組件,我們可以給A組件綁定一個事件,該事件函數體為Event.$emit('自定義事件名',A組件上的數據);,然后我們再在B組件的組件對象上的mounted(該組件掛載完成之后觸發執行的函數)函數體上寫上Event.$on('對應的自定義事件名',function(data){});其中的data即代表接收到的來自A組件上的數據。示例代碼如下所示:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="bower_components/vue/dist/vue.js"></script> <script> window.onload = function(){ var Event = new Vue(); Vue.component('my-aaa',{ template:'#ccc', data:function(){ return { msg1:'父組件的數據' }; }, mounted:function(){ Event.$on('sendtofahter',function(data){ this.msg1 = data; }.bind(this)); }, components:{ 'my-bbb':{ template:'#ddd', data:function(){ return { msg2:'子組件的數據' }; }, methods:{ send:function(){ Event.$emit('sendtofahter',this.msg2); } } } } }); var vm = new Vue({ el:'#box' }); }; </script> </head> <body> <div id="box"> <my-aaa></my-aaa> </div> <template id="ccc"> <div> <h3>{{msg1}}</h3> <my-bbb></my-bbb> </div> </template> <template id="ddd"> <div> <button @click="send()">send-to-father</button> <h3>{{msg2}}</h3> </div> </template> </body> </html> 

上述代碼可以實現與父組件獲取其子組件當中的數據的示例代碼一樣的效果。下面給出兩個兄弟組件之間通信的示例代碼:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="bower_components/vue/dist/vue.js"></script> <script> window.onload = function(){ var Event = new Vue(); Vue.component('my-aaa',{ template:'#ccc', data:function(){ return { msg1:'兄弟組件aaa的數據' }; }, mounted:function(){ Event.$on('sendtobrother',function(data){ this.msg1 = data; }.bind(this)); } }); Vue.component('my-bbb',{ template:'#ddd', data:function(){ return { msg2:'兄弟組件bbb的數據' }; }, methods:{ send:function(){ Event.$emit('sendtobrother',this.msg2); } } }); var vm = new Vue({ el:'#box' }); }; </script> </head> <body> <div id="box"> <my-aaa></my-aaa> <my-bbb></my-bbb> </div> <template id="ccc"> <div> <h3>{{msg1}}</h3> </div> </template> <template id="ddd"> <div> <button @click="send()">send-to-brother</button> <h3>{{msg2}}</h3> </div> </template> </body> </html> 

當我們點擊按鈕之后,顯示的結果為:


免責聲明!

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



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