父子元件2.0
阿新 • • 發佈:2018-11-08
在前面總結過vue1.0中的元件通訊,現在根據vue2.0的變化比較一下兩者的不同之處。
首先還是用一個例子回顧一下之前的父子元件通訊。
vue1.0
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="vue1.0.js"></script> </head> <body> <template id="child"> <div> <span>我是子元件</span> <input type="button" value="按鈕" @click="change"> <strong>{{msg}}</strong> </div> </template> <div id="box"> 父級: ->{{a}} <br> <child-com :msg="a"></child-com> </div> <script> new Vue({ el:'#box', data:{ a:'我是父元件資料' }, components:{ 'child-com':{ props:['msg'], template:'#child', methods:{ change(){ this.msg='被更改了' } } } } }); </script> </body> </html>
在上面的例子中,子元件是可以更改父元件的資料的,甚至可以通過新增sync實現同步修改,但是當我們把上面的js改為vue2.0的時候,會發現程式直接報錯了。
這是因為在vue2.0中的prop中提出了一個單向下行繫結:父級 prop 的更新會向下流動到子元件中,但是反過來則不行。這樣會防止從子元件意外改變父級元件的狀態,從而導致你的應用的資料流向難以理解。額外的,每次父級元件發生更新時,子元件中所有的 prop 都將會重新整理為最新的值。這意味著你不應該在一個子元件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制檯中發出警告。
針對子元件需要更改prop傳過來的值,官方文件給出了兩種辦法。
本地data
第一種方法是這個prop用來傳遞一個初始值,當子元件希望將這個初始值用作一個本地資料使用時,最好定義一個本地的data屬性並將這個prop用作其初始值。在下面的例子中,我們希望在子元件中使用父元件的資料a,首先在父元件中通過prop將這個資料傳遞到子元件,然後在子元件中定義一個b,這個b的初始值就是a,然後在子元件中對b進行操作。所以,此時只能更改b,並不能同步更改a。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="vue.js"></script> </head> <body> <template id="child"> <div> <span>我是子元件</span> <input type="button" value="按鈕" @click="change"> <strong>{{b}}</strong> </div> </template> <div id="box"> 父級: ->{{a}} <br> <child-com :msg="a"></child-com> </div> <script> new Vue({ el:'#box', data:{ a:'我是父元件資料' }, components:{ 'child-com':{ props:['msg'], data(){ return { b:this.msg } }, template:'#child', methods:{ change(){ this.b='被更改了' } } } } }); </script> </body> </html>
官方中還提供了一種使用計算屬性的方法。可以直接在官方檢視,這裡就不再演示了。
物件引用
除此之外,還有另外一種方法,那就是物件之間的引用,父元件不再是傳遞單一的基本型別資料給子元件,而是使用物件的形式進行傳遞,此時不僅能夠實現子元件資料更改,還能同步更改父元件資料。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="vue.js"></script> </head> <body> <template id="child"> <div> <span>我是子元件</span> <input type="button" value="按鈕" @click="change"> <strong>{{msg.a}}</strong> </div> </template> <div id="box"> 父級: ->{{giveData.a}} <br> <child-com :msg="giveData"></child-com> </div> <script> new Vue({ el:'#box', data:{ giveData:{ a:'我是父元件資料' } }, components:{ 'child-com':{ props:['msg'], template:'#child', methods:{ change(){ this.msg.a='被改了'; } } } } }); </script> </body> </html>
單一事件管理元件通訊。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="vue.js"></script> </head> <body> <div id="box"> <com-a></com-a> <com-b></com-b> <com-c></com-c> </div> <script> //準備一個空的例項物件 var Event=new Vue(); var A={ template:` <div> <span>我是A元件</span> -> {{a}} <input type="button" value="把A資料給C" @click="send"> </div> `, methods:{ send(){ Event.$emit('a-msg',this.a); } }, data(){ return { a:'我是a資料' } } }; var B={ template:` <div> <span>我是B元件</span> -> {{a}} <input type="button" value="把B資料給C" @click="send"> </div> `, methods:{ send(){ Event.$emit('b-msg',this.a); } }, data(){ return { a:'我是b資料' } } }; var C={ template:` <div> <h3>我是C元件</h3> <span>接收過來的A的資料為: {{a}}</span> <br> <span>接收過來的B的資料為: {{b}}</span> </div> `, data(){ return { a:'', b:'' } }, mounted(){ //接收A元件的資料 Event.$on('a-msg',function(a){ this.a=a; }.bind(this)); //接收B元件的資料 Event.$on('b-msg',function(a){ this.b=a; }.bind(this)); } }; new Vue({ el:'#box', components:{ 'com-a':A, 'com-b':B, 'com-c':C } }); </script> </body> </html>
主要包括三個步驟:
- 準備一個空的例項物件 var Event=new Vue();
- 傳送資料 Event.$emit(事件名稱, 資料)
- 接收資料 Event.$on(事件名稱,function(data){ }.bind(this));