Vue2.4中$attrs和$listeners的使用-學習筆記
阿新 • • 發佈:2019-01-29
首先我們來看下面的一張圖,圖中表示一個多級元件巢狀的情形。
現在我們來討論一種情況,A元件與C元件怎麼通訊,我們有多少種解決方案?
- 我們使用VueX來進行資料管理,但是如果專案中多個元件共享狀態比較少,專案比較小,並且全域性狀態比較少,那使用VueX來實現該功能,並沒有發揮出VueX的威力。
- 使用B來做中轉站,當A元件需要把資訊傳給C元件時,B接受A元件的資訊,然後利用屬性傳給C元件,這是一種解決方案,但是如果巢狀的元件過多,會導致程式碼繁瑣,程式碼維護比較困難;如果C中狀態的改變需要傳遞給A, 使用事件系統一級級往上傳遞 。本來
- 自定義一個Vue 中央資料匯流排,這個情況適合碰到元件跨級傳遞訊息,但是使用VueX感覺又有點浪費的專案中,但是缺點是,碰到多人合作時,程式碼的維護性較低,程式碼可讀性低
在很多開發情況下,我們只是想把A元件的資訊傳遞給C元件,如果使用props 繫結來進行資訊的傳遞,雖然能夠實現,但是程式碼並不美觀。
在vue2.4中,為了解決該需求,引入了$attrs 和$listeners , 新增了inheritAttrs 選項。 在版本2.4以前,預設情況下父作用域的不被認作props的屬性屬性百年孤獨,將會“回退”且作為普通的HTML特性應用在子元件的根元素上。如下列的例子
父元件demo程式碼如下
<template> <div> <child-dom :foo="foo" :coo="foo" > </child-dom> </div> </template> <script> import childDom from "./ChildDom.vue"; export default { data() { return { foo:"Hello, world", coo:"Hello,rui" } }, components:{childDom}, } </script>
子元件child-dom程式碼如下
<template> <div> <p>foo:{{foo}}</p> </div> </template> <script> export default { name:'child-dom' props:["foo"] } </script>
當顯示父元件時,檢視Dom結構,結構如下
在2.4中新增選項inheritAttrs inheritAttrs的預設值為true, 將inheritAttrs的值設為false, 這些預設的行為會禁止掉。但是通過例項屬性$attrs
修改子元件程式碼如下
<template> <div> <p>foo:{{foo}}</p> <p>attrs:{{$attrs}}</p> <childDomChild v-bind="$attrs"></childDomChild> </div> </template> <script> import childDomChild from './childDomChild'; export default { name:'child-dom' props:["foo"], inheritAttrs:false, } </script>
新增子元件 childDomChild
<template> <div> <p>coo:{{coo}}</p> </div> </template> <script> export default { name:'childDomChild' props:["coo"], inheritAttrs:false } </script>
輸出的結果如下
從上面的程式碼,可以看出使用$attrs ,inheritAttrs 屬性 能夠使用簡潔的程式碼,將A元件的資料傳遞給C元件 ,該場景的使用範圍還是挺廣的。
此時我們又想到了一個問題,c元件的資訊,怎麼同步給a元件呢?
vue2.4版本新增了$listeners 屬性,我們在b元件上 繫結 v-on=”$listeners”, 在a元件中,監聽c元件觸發的事件。就能把c元件發出的資料,傳遞給a元件。
A元件程式碼更新如下
<template> <div> <child-dom :foo="foo" :coo="coo" v-on:upRocket="reciveRocket" > </child-dom> </div> </template> <script> import childDom from "@/components/ChildDom.vue"; export default { name:'demoNo', data() { return { foo:"Hello, world", coo:"Hello,rui" } }, components:{childDom}, methods:{ reciveRocket(){ console.log("reciveRocket success") } } } </script>
b元件更新如下
<template> <div> <p>foo:{{foo}}</p> <p>attrs:{{$attrs}}</p> <childDomChild v-bind="$attrs" v-on="$listeners"></childDomChild> </div> </template> <script> import childDomChild from './childDomChild'; export default { name:'child-dom' props:["foo"], inheritAttrs:false, } </script>
c元件更新如下
<template> <div> <p>coo:{{coo}}</p> <button @click="startUpRocket">我要發射火箭</button> </div> </template> <script> export default { name:'childDomChild', props:['coo'], methods:{ startUpRocket(){ this.$emit("upRocket"); console.log("startUpRocket") } } } </script>
執行效果如下
現在我們應該清楚了$attrs,$listerners,inheritAttrs 的作用了吧