Vue父子組件傳值&自定義事件方式
Vue 父子組件傳值&自定義事件
因?yàn)関ue 的數(shù)據(jù)是單向流動(dòng)的,這是為了避免數(shù)據(jù)污染。
在官方文檔中也說(shuō)到:所有的 prop 都使得其父子 prop 之間形成了一個(gè)單向下行綁定:父級(jí) prop 的更新會(huì)向下流動(dòng)到子組件中,但是反過(guò)來(lái)則不行。
這樣會(huì)防止從子組件意外改變父級(jí)組件的狀態(tài),從而導(dǎo)致你的應(yīng)用的數(shù)據(jù)流向難以理解。
大致歸納一下:父?jìng)髯?-傳值、子傳父--傳事件
父?jìng)髯樱焊附M件可以傳遞任何類型的數(shù)據(jù)給子組件
如果傳遞的數(shù)據(jù)是對(duì)象格式的,那么在子組件 內(nèi)部監(jiān)聽(tīng) watch 的時(shí)候,需要使用深度監(jiān)聽(tīng),也就是添加 deep : true ,也就是下面的子組件的監(jiān)聽(tīng)方式,如果是別的格式的,例如,字符串、數(shù)字、布爾值、 數(shù)組格式等,那就是普通監(jiān)聽(tīng)就好了
父組件代碼
在父組件中 通過(guò) v-bind 的縮寫(xiě)形式 :listData='listData' 綁定了data 內(nèi)部的數(shù)據(jù),第一個(gè) listData 只是一個(gè)名字,為了方便辨認(rèn),所以寫(xiě)的相同。 第二個(gè) listData 則是 data 內(nèi)部的數(shù)據(jù)
<template> <div> <h3>我是father</h3> <Children :listData='listData' :xxx='xxx' :listObj='listObj'></Children> //子組件傳遞了一個(gè)數(shù)組、一個(gè)字符串、一個(gè)對(duì)象 </div> </template> <script> import Children from './children' //引入子組件 export default { data () { return { xxx:'123', listData: [{ id: 1, name: "TCL彩電", price: 1000, num: 1, img: "../../../assets/a.jpg" }], listObj: { name: "aaa", age: 18 } } }, components : { Children //注冊(cè)子組件 }, } </script>
子組件代碼
1、通過(guò) props 接收父組件傳遞過(guò)來(lái)的數(shù)據(jù),規(guī)范要求寫(xiě)出數(shù)據(jù)的類型以及默認(rèn)值,如果數(shù)據(jù)是數(shù)組或?qū)ο笮问降?,需要使用函?shù)返回,不然控制臺(tái)會(huì)報(bào)錯(cuò)。
2、props 接收數(shù)據(jù)之后,需要使用數(shù)據(jù),這個(gè)時(shí)候需要用到 watch 監(jiān)聽(tīng)器。對(duì)象監(jiān)聽(tīng)需要用到 deep 深度監(jiān)聽(tīng),如果需要組件第一次進(jìn)來(lái)之后就開(kāi)始監(jiān)聽(tīng)數(shù)據(jù),那么需要 添加 immediate: true
<template> <div> <h3>我是children</h3> </div> </template> <script> export default { props: { listData: { type: Array, default: () => [] }, xxx:{ type:String, default : '' }, listObj:{ type: Object, default: () => {} } }, watch: { listData:{ handler(n,o) { console.log(n,o) } }, xxx:{ handler(n) { console.log(n) } }, listObj:{ handler(n,o) { console.log(n,o) }, deep: true, immediate: true, }, } }; </script>
子傳父--傳事件:子組件傳遞數(shù)據(jù)給父組件時(shí)存在三種方式,但是都是通過(guò)事件傳遞
1、父組件傳遞 函數(shù)類型的props 給子組件,實(shí)現(xiàn)子組件向父組件傳遞數(shù)據(jù)
在父組件中引入子組件,向子組件中 通過(guò) v-bind( 簡(jiǎn)寫(xiě)為 : ) 綁定一個(gè) test 屬性 ,該 test 屬性對(duì)應(yīng)的值則是 methods 中定義的方法。
<template> <div id="app"> <School :test="test"/> </div> </template> methods: { test(val) { console.log(val,'這是子組件傳遞過(guò)來(lái)的數(shù)據(jù)') }, },
定義子組件,以及子組件事件
<template> <div> <p class="demo" @click="goto">School組件</p> </div> </template>
在子組件中接收該 test 屬性,定義數(shù)據(jù),定義組件方法。其實(shí)props 可以直接寫(xiě)成一個(gè)數(shù)組,不去定義類型,默認(rèn)值以及是否必傳,但是推薦還是寫(xiě)全一點(diǎn),這樣編譯的時(shí)候會(huì)校驗(yàn),提高代碼質(zhì)量
export default ({ // props:['test'], props: { test: { type: Function, default: () => {}, required: true, } }, data() { return { msg:'子組件數(shù)據(jù)' } }, methods: { goto() { this.test(this.msg) } }, })
點(diǎn)擊觸發(fā) goto 事件,找到當(dāng)前 props 中接收的 test 函數(shù) ( props 接收的參數(shù),都被Vue 底層處理過(guò)之后放在了 當(dāng)前組件實(shí)例對(duì)象上,所以可以直接通過(guò) this.xxx 拿到 )
控制臺(tái)上打印了子組件數(shù)據(jù)??梢钥吹阶咏M件傳遞的數(shù)據(jù)被打印了,表示父組件中綁定的 test 事件被執(zhí)行了
2、通過(guò) v-on( @ ) 與 $emit 實(shí)現(xiàn)子組件向父組件傳遞數(shù)據(jù)
App 組件中引入 School 子組件,且綁定 自定義事件 test。
<School @test="test"/> test(val) { console.log(val,'這是子組件傳遞過(guò)來(lái)的數(shù)據(jù)') },
子組件模板、數(shù)據(jù)、樣式不變,只是 goto 方法內(nèi)部邏輯變更
methods: { goto() { this.$emit('test',this.msg) } },
點(diǎn)擊觸發(fā) goto 事件,通過(guò) $emit 觸發(fā) test 事件,根據(jù)名稱找到 父組件中的 test 屬性對(duì)應(yīng)的方法,執(zhí)行該方法。結(jié)果與 props 傳遞函數(shù)參數(shù)一致
3、通過(guò) ref 以及 $on、$emit 三個(gè) api 實(shí)現(xiàn) 父組件通過(guò) 自定義事件接收子組件參數(shù)
$on
:監(jiān)聽(tīng)當(dāng)前實(shí)例上的自定義事件。事件可以由 vm.$emit 觸發(fā)?;卣{(diào)函數(shù)會(huì)接收所有傳入事件觸發(fā)函數(shù)的額外參數(shù)。$emit
:觸發(fā)當(dāng)前實(shí)例上的事件。附加參數(shù)都會(huì)傳給監(jiān)聽(tīng)器回調(diào)。
App 組件中引入 Schoo 組件,且給 School 子組件添加了 ref 屬性,定義 test 函數(shù)
<School ref='student'/> test(val) { console.log(val,'這是子組件傳遞過(guò)來(lái)的數(shù)據(jù)') },
如果想使用這個(gè)方法去獲取子組件數(shù)據(jù),就需要用到 $on() 這個(gè)方法。現(xiàn)在假設(shè),當(dāng)父組件掛載時(shí),我就要獲取到子組件的值,我就應(yīng)該在 父組件 的 mounted 生命周期中 使用 this.$refs.xxx來(lái)獲取當(dāng)前組件的實(shí)例對(duì)象,至于 $on() 這個(gè)方法,則是 掛載到 Vue 實(shí)例對(duì)象的原型上的,所以 組件實(shí)例對(duì)象 和 Vue 實(shí)例對(duì)象 都能使用 $on() 。
在這里就是 通過(guò) $on 注冊(cè)或者叫創(chuàng)建了一個(gè) qwe 的自定義事件,且該自定義事件的回調(diào)函數(shù)是寫(xiě)在 methods 中的 getname
mounted() { this.$refs.student.$on('qwe', this.test) }
父組件的工作已經(jīng)完了,現(xiàn)在該看看子組件了。子組件更簡(jiǎn)單了,和上面 第二種方法一樣,通過(guò) $emit() 這個(gè)方法來(lái)觸發(fā)父組件定義的 qwe 方法,且將子組件 數(shù)據(jù)傳遞出去。
goto() { this.$emit('test',this.msg) }
當(dāng)我點(diǎn)擊 School 組件時(shí),執(zhí)行 goto 方法,通過(guò) $emit 觸發(fā)父組件自定義的 qwe 方法,且將參數(shù)傳遞給父組件。
父組件通過(guò) $on 監(jiān)聽(tīng) qwe 方法,發(fā)現(xiàn)被觸發(fā)了,執(zhí)行其回調(diào)函數(shù) this.test,且 $emit 傳遞的參數(shù),都會(huì)當(dāng)做形參傳遞到回調(diào)函數(shù)中
$on 和 v-on 的區(qū)別
這么一看哈,其實(shí)我在子組件上使用 v-on( @ ) 和我使用 $on 做到的事情是一樣的啊,那為啥還要來(lái)個(gè) $on 這個(gè)玩意。
- 第一點(diǎn):$on 只能監(jiān)聽(tīng)當(dāng)前實(shí)例上的自定義事件,而 v-on 用在普通元素上時(shí),只能監(jiān)聽(tīng)原生DOM事件。用在自定義元素組件上時(shí),也可以監(jiān)聽(tīng)子組件觸發(fā)的自定義事件。
- 第二點(diǎn):$on 更加靈活,如果我想要我的自定義事件異步綁定,通過(guò) v-on 是無(wú)法做到的,因?yàn)?v-on 指令在 模板編譯的時(shí)候,就被Vue 底層處理過(guò)了,在渲染的時(shí)候直接就會(huì)綁定事件,但是 $on 的自由度更高。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue+Openlayers自定義軌跡動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了Vue+Openlayers自定義軌跡動(dòng)畫(huà),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09Vue-cli框架實(shí)現(xiàn)計(jì)時(shí)器應(yīng)用
這篇文章主要為大家詳細(xì)介紹了Vue-cli框架實(shí)現(xiàn)計(jì)時(shí)器應(yīng)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08element的el-date-picker組件實(shí)現(xiàn)只顯示年月日時(shí)分效果(不顯示秒)
最近遇到這樣的需求使用element的el-date-picker組件,只顯示時(shí)分,不顯示秒,下面小編給大家分享element的el-date-picker組件實(shí)現(xiàn)只顯示年月日時(shí)分效果,感興趣的朋友一起看看吧2024-08-08解決vue-photo-preview 異步圖片放大失效的問(wèn)題
這篇文章主要介紹了解決vue-photo-preview 異步圖片放大失效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07基于Vue+Webpack拆分路由文件實(shí)現(xiàn)管理
這篇文章主要介紹了基于Vue+Webpack拆分路由文件實(shí)現(xiàn)管理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11vue實(shí)現(xiàn)動(dòng)態(tài)路由的方法及路由原理解析
這篇文章主要介紹了路由原理及vue實(shí)現(xiàn)動(dòng)態(tài)路由,Vue Router 提供了豐富的 API,可以輕松地實(shí)現(xiàn)路由功能,并支持路由參數(shù)、查詢參數(shù)、命名路由、嵌套路由等功能,可以滿足不同應(yīng)用程序的需求,需要的朋友可以參考下2023-06-06