vue $attrs和$listeners的使用與區(qū)別
首先讓我們看一下這張圖,表示了一個(gè)多級(jí)關(guān)聯(lián)的組件嵌套
為什么要用$attrs
和 $listeners
先讓我們來(lái)想一種情況,就是組件A跟組件C怎么通信,我們可以有多少中解決方案?
- 看到這種情況,大多數(shù)人應(yīng)該會(huì)想到用vuex來(lái)進(jìn)行數(shù)據(jù)通信吧,但是如果項(xiàng)目中多個(gè)組件中的共享狀態(tài)很少,且項(xiàng)目比較小,全局?jǐn)?shù)據(jù)通信也很少,那我們用vuex來(lái)實(shí)現(xiàn)這個(gè)功能,就感覺(jué)有點(diǎn)殺雞用牛刀了
- 我們可以使用組件B來(lái)做通信的中轉(zhuǎn)站,當(dāng)組件A需要把數(shù)據(jù)傳到組件C時(shí),組件A通過(guò)props將數(shù)據(jù)傳給組件B,然后組件B再用props傳給組件C,這是一種解決方案,但是如果嵌套的組件過(guò)多,就會(huì)導(dǎo)致代碼冗余且繁瑣,維護(hù)就比較困難,而且如果組件C也要將數(shù)據(jù)傳給組件A,也要一層一層往上傳遞,就更麻煩了
- 自定義一個(gè)Vue數(shù)據(jù)總線,這種適合組件跨級(jí)傳遞數(shù)據(jù),但是缺點(diǎn)是碰到多人合作時(shí),會(huì)導(dǎo)致代碼的維護(hù)性較低,代碼可讀性也較低
- 還有一種解決方案,就是用provide inject,但是這種方式,官方不推薦,因?yàn)?strong>這個(gè)方法真的是太不好管控了,比如說(shuō)我在根組件provide了this,孫孫重孫組件去使用了this里面的一個(gè)變量,這時(shí)候很難去跟蹤到這個(gè)變量的出處了,而且你也并不知道,項(xiàng)目中哪個(gè)組件有用到這個(gè)變量,有沒(méi)有在其他組件中進(jìn)行改變,所以這個(gè)api在項(xiàng)目中很少人使用,但是很多人拿來(lái)寫(xiě)組件用
在很多開(kāi)發(fā)情況下,我們只是想把組件A的數(shù)據(jù)傳給組件C,如果用props來(lái)進(jìn)行組件通信的話,雖然可以實(shí)現(xiàn),但是代碼可讀性上不強(qiáng),且難維護(hù)。
所以這時(shí)候,我們的主角$attrs
和 $listeners
就出現(xiàn)了
$attrs
和 $listeners
的用法
在vue2.4中,為了解決該需求,引入了$attrs
和$listeners
, 新增了inheritAttrs
選項(xiàng)。 在版本2.4以前,默認(rèn)情況下父作用域的不被認(rèn)作props的屬性屬性百年孤獨(dú),將會(huì)“回退”且作為普通的HTML特性應(yīng)用在子組件的根元素上。如下列的例子
父組件的代碼:
<template> <div> <child-dom :foo="foo" :bar="bar"></child-dom> </div> </template> ? <script> import ChildDom from "../components/attrs/ChildDom.vue"; export default { components: { ChildDom, }, data() { return { foo: "foo", bar: "bar", }; }, }; </script>
子組件的代碼:
<template> <div> <p>foo:{{ foo }}</p> </div> </template> ? <script> export default { props: ["foo"], }; </script>
我們先看一下這樣寫(xiě)的時(shí)候,控制臺(tái)打印出來(lái)的dom結(jié)構(gòu)是這樣的:
在2.4中新增選項(xiàng)inheritAttrs
,inheritAttrs
的默認(rèn)值為true, 將inheritAttrs
的值設(shè)為false, 這些默認(rèn)的行為會(huì)禁止掉。但是通過(guò)實(shí)例屬性 $attrs
,可以將這些特性生效,且可以通過(guò)v-bind
綁定到子組件的非根元素上。
將子組件的代碼修改一下:
<template> <div> <p>foo:{{ foo }}</p> <p>attrs: {{ $attrs }}</p> <dom-child v-bind="$attrs"></dom-child> </div> </template> ? <script> import DomChild from "./DomChild.vue"; export default { props: ["foo"], inheritAttrs: false, components: { DomChild, }, }; </script>
然后在加一個(gè)孫組件
<template> <div> <p>bar:{{ bar }}</p> </div> </template> ? <script> export default { props: ["bar"], }; </script>
頁(yè)面顯示如下:
從上面的代碼,可以看出使用$attrs
,inheritAttrs
屬性能夠使用簡(jiǎn)潔的代碼,將組件A的數(shù)據(jù)傳遞給 組件C,該場(chǎng)景的使用范圍還是挺廣的。
那我們現(xiàn)在來(lái)看看組件C怎么傳值給組件A?
vue2.4版本新增了$listeners
屬性,我們?cè)诮M件B上 綁定 v-on=”$listeners”
, 在組件A中,監(jiān)聽(tīng)組件C觸發(fā)的事件。就能把組件C發(fā)出的數(shù)據(jù),傳遞給組件A。
修改一下父組件的代碼:
<template> <div> <child-dom :foo="foo" :bar="bar" @upFoo="update"></child-dom> </div> </template> ? <script> import ChildDom from "../components/attrs/ChildDom.vue"; export default { components: { ChildDom, }, data() { return { foo: "foo", bar: "bar", }; }, methods: { update(val) { this.foo = val; console.log("update success"); }, }, }; </script>
子組件代碼:
<template> <div> <p>foo:{{ foo }}</p> <p>attrs: {{ $attrs }}</p> <dom-child v-bind="$attrs" v-on="$listeners"></dom-child> </div> </template> ? <script> import DomChild from "./DomChild.vue"; export default { props: ["foo"], inheritAttrs: false, components: { DomChild, }, }; </script>
孫組件代碼:
<template> <div> <p>bar:{{ bar }}</p> <button @click="startUpFoo">我要更新foo</button> </div> </template> ? <script> export default { props: ["bar"], methods: { startUpFoo() { this.$emit("upFoo", "foooooooooooo"); console.log("startUpFoo"); }, }, }; </script>
運(yùn)行結(jié)果:
現(xiàn)在我們應(yīng)該清楚了$attrs
,$listerners
,inheritAttrs
的作用了吧
到此這篇關(guān)于vue $attrs和$listeners的使用與區(qū)別的文章就介紹到這了,更多相關(guān)vue $attrs $listeners內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
程序員應(yīng)該知道的vuex冷門(mén)小技巧(超好用)
Vue基本用法很容易上手,但是有很多優(yōu)化的寫(xiě)法你就不一定知道了,下面這篇文章主要給大家介紹了關(guān)于程序員應(yīng)該知道的vuex冷門(mén)小技巧的相關(guān)資料,需要的朋友可以參考下2022-05-05VUE+Canvas實(shí)現(xiàn)簡(jiǎn)單五子棋游戲的全過(guò)程
這篇文章主要給大家介紹了關(guān)于VUE+Canvas實(shí)現(xiàn)簡(jiǎn)單五子棋游戲的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05如何解決vuex在頁(yè)面刷新后數(shù)據(jù)被清除的問(wèn)題
這篇文章主要介紹了如何解決vuex在頁(yè)面刷新后數(shù)據(jù)被清除的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05關(guān)于SpringBoot與Vue交互跨域問(wèn)題解決方案
最近在利用springboot+vue整合開(kāi)發(fā)一個(gè)前后端分離的個(gè)人博客網(wǎng)站,所以這一篇總結(jié)一下在開(kāi)發(fā)中遇到的一個(gè)問(wèn)題,關(guān)于解決在使用vue和springboot在開(kāi)發(fā)前后端分離的項(xiàng)目時(shí),如何解決跨域問(wèn)題。在這里分別分享兩種方法,分別在前端vue中解決和在后臺(tái)springboot中解決。2021-10-10vue3使用vuedraggable實(shí)現(xiàn)拖拽功能
這篇文章主要為大家詳細(xì)介紹了vue3使用vuedraggable實(shí)現(xiàn)拖拽功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04vue3.0自定義指令(drectives)知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整體了一篇關(guān)于vue3.0自定義指令(drectives)知識(shí)點(diǎn)總結(jié),有興趣的朋友們可以學(xué)習(xí)下。2020-12-12Vuex的插件vuex-persistedstate數(shù)據(jù)持久化存儲(chǔ)操作
這篇文章主要介紹了Vuex的插件vuex-persistedstate數(shù)據(jù)持久化存儲(chǔ)操作,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-12-12