vue父子組件
1、父子組件
在上一篇隨筆中展示了vue的組件,當我們繼續在組件中寫組件,形成組件嵌套的時候,就是我們所說的父子組件了。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="bower_components/vue/dist/vue.js"></script> <style> </style> </head> <body> <div id="box"> <aaa></aaa> </div> <script> var vm=new Vue({ el:‘#box‘, data:{ a:‘aaa‘ }, components:{ ‘aaa‘:{ template:‘<h2>我是aaa組件</h2><bbb></bbb>‘, components:{ ‘bbb‘:{ template:‘<h3>我是bbb組件</h3>‘ } } } } }); </script> </body> </html>
在上面的例子中,外層的組件aaa就是父組件,內層的bbb組件便是子組件了。
2、子組件獲取父組件的數據
我們知道,每個組件都可以有自己的data屬性,組件的數據在整個組件的內部都是可以使用的,那麽在下面的例子中,組件bbb是aaa的子組件,存在於組件aaa的內部,為什麽不能使用aaa的數據呢?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="bower_components/vue/dist/vue.js"></script> </head> <body> <div id="box"> <aaa></aaa> </div> <template id="aaa"> <h1>11111</h1> <bbb></bbb> </template> <script> var vm=new Vue({ el:‘#box‘, data:{ a:‘aaa‘ }, components:{ ‘aaa‘:{ data(){ return { msg2:‘我是父組件的數據‘ } }, template:‘#aaa‘, components:{ ‘bbb‘:{ template:‘<h3>我是bbb組件->{{msg2}}</h3>‘ } } } } }); </script> </body> </html>
這是因為,在vue中,組件實例的作用域是孤立的,默認情況下,父子組件的數據是不能共享的,也就是說,子組件是不能直接訪問父組件的數據的。為此,vue給我們提供了一個數據傳遞的選項prop,用來將父組件的數據傳遞給子組件。具體使用如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="bower_components/vue/dist/vue.js"></script> </head> <body> <div id="box"> <aaa></aaa> </div> <template id="aaa"> <h1>11111</h1> <bbb :m="msg"></bbb> </template> <script> var vm=new Vue({ el:‘#box‘, data:{ a:‘aaa‘ }, components:{ ‘aaa‘:{ data(){ return { msg:‘我是父組件的數據‘ } }, template:‘#aaa‘, components:{ ‘bbb‘:{ props:[‘m‘], template:‘<h3>我是bbb組件->{{m}}</h3>‘ } } } } }); </script> </body> </html>
在使用prop時,我們需要在子組件中使用v-bind將父組件數據和子組件的自定義屬性m進行綁定,這個自定義m就是我們在子組件的props中定義。一個組件默認可以擁有任意數量的prop,任何值都可以傳遞給任何的prop,所以我們在上面使用的是props來存儲prop列表,這個props既可以是個數組,也可以是個對象。需要註意的是,props中的prop列表需要使用駝峰式命令法。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="bower_components/vue/dist/vue.js"></script> </head> <body> <div id="box"> <aaa></aaa> </div> <template id="aaa"> <h1>11111</h1> <bbb :m="msg2" :my-msg="msg"></bbb> </template> <script> var vm=new Vue({ el:‘#box‘, data:{ a:‘aaa‘ }, components:{ ‘aaa‘:{ data(){ return { msg:111, msg2:‘我是父組件的數據‘ } }, template:‘#aaa‘, components:{ ‘bbb‘:{ props:{ ‘m‘:String, ‘myMsg‘:Number }, template:‘<h3>我是bbb組件->{{m}} <br> {{myMsg}}</h3>‘ } } } } }); </script> </body> </html>
在父組件通過props向子組件傳遞數據時,根據需求不同,分為靜態props和動態props,所謂靜態props,就是子組件要顯示地用props選項聲明它期待獲取的數據;而動態props則是動態的綁定父組件的數據到子組件的props,使用v-bind進行綁定,當父組件的數據變化時,該變化也會傳遞給子組件。另外需要說明的是數字的傳遞,在使用靜態props傳遞數字時,它在子組件中的值是字符串,如果想傳遞一個實際的 number,需要使用 v-bind,從而讓它的值被當作JS表達式計算 ,可以使用動態props,在data屬性中設置對應的數字1。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="bower_components/vue/dist/vue.js"></script> </head> <body> <div id="box"> <aaa></aaa> </div> <template id="aaa"> <h1>11111</h1> <bbb message="靜態props" c-message="ppp" :c-mess="pmsg" mess1="1" :mess2="2" :mess3="num"></bbb> </template> <script> var vm=new Vue({ el:‘#box‘, data:{ a:‘aaa‘ }, components:{ ‘aaa‘:{ data(){ return { ‘pmsg‘:‘動態props‘, ‘num‘:3, } }, template:‘#aaa‘, components:{ ‘bbb‘:{ props:[‘message‘,‘cMessage‘,‘c-mess‘,‘mess1‘,‘mess2‘,‘mess3‘], template: ` <div> <div>{{message}} ---- {{cMessage}} --- {{cMess}}</div> <div> {{mess1}}是{{ type(mess1) }}類型<br> {{mess2}}是{{ type(mess2) }}類型<br> {{mess3}}是{{ type(mess3) }}類型<br> </div> <div> `, methods:{ type(text){ return typeof text; } } } } } } }); </script> </body> </html>
3、父組件獲取子組件的數據
和上面不一樣的是,父組件想要獲取子組件的數據時,需要子組件通過emit主動將自己的數據發送給父組件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="bower_components/vue/dist/vue.js"></script> </head> <body> <div id="box"> <aaa></aaa> </div> <template id="aaa"> <span>我是父級 -> {{msg}}</span> <bbb @child-msg="get"></bbb> </template> <template id="bbb"> <h3>子組件-</h3> <input type="button" value="send" @click="send"> </template> <script> var vm=new Vue({ el:‘#box‘, data:{ a:‘aaa‘ }, components:{ ‘aaa‘:{ data(){ return { msg:111, msg2:‘我是父組件的數據‘ } }, template:‘#aaa‘, methods:{ get(msg){ this.msg=msg; } }, components:{ ‘bbb‘:{ data(){ return { a:‘我是子組件的數據‘ } }, template:‘#bbb‘, methods:{ send(){ this.$emit(‘child-msg‘,this.a); } } } } } } }); </script> </body> </html>
首先,我們需要在子組件中觸發一個主動發送數據的事件,上面的例子中是一個點擊事件send;其次,在點擊事件中使用emit方法,這個emit接收兩個參數:傳遞數據的事件和需要傳遞的數據,這個傳遞數據的事件也是自定義的;然後在父組件中引用子組件,並在引用的子組件中使用on監聽上一步傳遞數據的事件,上面的例子中是child-msg;最後在父組件中使用這個事件,這個事件帶有一個參數,就是從子組件發送過來的數據。
vue父子組件