探討一下子父組件之間的傳值通信問題:
首先是環(huán)境搭建:
打開git ,運(yùn)行 npm install --global vue-cli 這是安裝vue的命令行
vue init webpack vue-demo 這是vue基于webpack的模板項(xiàng)目
cd vue-demo 進(jìn)入vue-demo文件夾
npm install 安裝package.json中依賴的node_modules
npm run dev 運(yùn)行該項(xiàng)目
接著我們進(jìn)入Demo,首先我們可以刪除掉模板項(xiàng)目中src/components/Hello.vue,然后在App.vue中刪除對于Hello子組件的注冊和使用還有一些其他無關(guān)緊要的東西,此時(shí)的App.vue應(yīng)為這樣:
一.父組件向子組件傳值
1.創(chuàng)建子組件,在src/components/文件夾下新建一個(gè)Child.vue
2.Child.vue的中創(chuàng)建props,然后創(chuàng)建一個(gè)名為message的屬性
3.在App.vue中注冊Child組件,并在template中加入child標(biāo)簽,標(biāo)簽中添加message屬性并賦值
4.保存修改的文件,查看瀏覽器
5.我們依然可以對message的值進(jìn)行v-bind動(dòng)態(tài)綁定:
此時(shí)瀏覽器中
父組件向子組件傳值成功
總結(jié)一下:
子組件在props中創(chuàng)建一個(gè)屬性,用以接收父組件傳過來的值;
父組件中注冊子組件;
在子組件標(biāo)簽中添加子組件props中創(chuàng)建的屬性;
把需要傳給子組件的值賦給該屬性。
注意事項(xiàng):在利用props實(shí)現(xiàn)傳值的過程中理論上是要實(shí)現(xiàn)單向傳遞,即父組件改變相關(guān)參數(shù)的值,子組件也相應(yīng)變化,但是子組件對參數(shù)的改變不應(yīng)該影響父組件。但是當(dāng)props中接收的是父組件傳遞的引用類型(對象或者是數(shù)組)時(shí),在子組件中對數(shù)據(jù)改變時(shí),父組件中的數(shù)據(jù)也會(huì)相應(yīng)的改變,因?yàn)閮烧呤侵赶虻耐坏刂穬?nèi)存。如果不想子組件的改變影響父組件可以利用深拷貝,將接受的數(shù)據(jù)進(jìn)行深拷貝后在子組件中使用,而不直接操作接受的數(shù)據(jù)。深拷貝可以直接利用ES6中的obj=Object。assign({},myMessage)(在computed中定義),這樣子組件的改動(dòng)將不會(huì)影響到父組件。
二.子組件向父組件傳值利用事件機(jī)制
子組件通過this.$emit()派發(fā)事件,父組件利用v-on對事件進(jìn)行監(jiān)聽,實(shí)現(xiàn)參數(shù)的傳遞。
1.在子組件中創(chuàng)建一個(gè)按鈕,給按鈕綁定一個(gè)點(diǎn)擊事件
2.在響應(yīng)該點(diǎn)擊事件的函數(shù)中使用$emit來觸發(fā)一個(gè)自定義事件,并傳遞一個(gè)參數(shù):
3.在父組件中的子標(biāo)簽中監(jiān)聽該自定義事件并添加一個(gè)響應(yīng)該事件的處理方法:
同時(shí)當(dāng)有組件嵌套時(shí)則需要利用該機(jī)制一層一層的觸發(fā)到指定層,不然直接在頂層監(jiān)聽子組件的子組件的事件是監(jiān)聽不到的,需要先向父組件派發(fā),父組件在向上層觸發(fā)。
4.保存修改的文件,在瀏覽器中點(diǎn)擊按鈕
子組件向父組件傳值成功
總結(jié)一下:
子組件中需要以某種方式例如點(diǎn)擊事件的方法來觸發(fā)一個(gè)自定義事件;
將需要傳的值作為$emit的第二個(gè)參數(shù),該值將作為實(shí)參傳給響應(yīng)自定義事件的方法;
在父組件中注冊子組件并在子組件標(biāo)簽上綁定對自定義事件的監(jiān)聽。
example2:
子組件:
this.$emit('changeCart',event.target)/*向父組件派發(fā)事件,同時(shí)傳遞參數(shù)event.target,后面的參數(shù)的個(gè)數(shù)不限*/
父組件:
<v-cartcontrol :food="food" v-on:changeCart="changeCart"></v-cartcontrol>
三、利用ref屬性可以獲取到dom元素或者是子組件,從而可以調(diào)用子組件的方法(注意2.0版本用ref取代了el)
1、當(dāng)ref直接定義在dom元素上時(shí),則通過this.$refs.name可以獲取到dom對dom進(jìn)行原生的操作:
<divclass="foods-wrapper" ref="foods-wrapper">
通過this.$refs獲取到dom進(jìn)行操作(注意ref屬性的命名不能用駝峰,同時(shí)獲取的時(shí)候也是)
let menuList=this.$refs['menu-wrapper'].getElementsByClassName('menu-list-hook');//此處如果用this.$refs["menuWrapper"]將獲取不到元素
2、通過在引用的子組件上使用ref屬性實(shí)現(xiàn)父組件調(diào)用子組件的方法以及屬性
在父組件中引用子組件并定義ref
<v-food ref="selectfood"></v-food>
調(diào)用定義在子組件中的方法show
this.$refs.selectfood.show();//同時(shí)也可以調(diào)用子組件中的屬性
在通信中,無論是子組件向父組件傳值還是父組件向子組件傳值,他們都有一個(gè)共同點(diǎn)就是有中間介質(zhì),子向父的介質(zhì)是自定義事件,父向子的介質(zhì)是props中的屬性。抓準(zhǔn)這兩點(diǎn)對于父子通信就好理解了。