vue $attrs和$listeners的使用與區(qū)別
首先讓我們看一下這張圖,表示了一個多級關聯(lián)的組件嵌套

為什么要用$attrs 和 $listeners
先讓我們來想一種情況,就是組件A跟組件C怎么通信,我們可以有多少中解決方案?
- 看到這種情況,大多數(shù)人應該會想到用vuex來進行數(shù)據(jù)通信吧,但是如果項目中多個組件中的共享狀態(tài)很少,且項目比較小,全局數(shù)據(jù)通信也很少,那我們用vuex來實現(xiàn)這個功能,就感覺有點殺雞用牛刀了
- 我們可以使用組件B來做通信的中轉站,當組件A需要把數(shù)據(jù)傳到組件C時,組件A通過props將數(shù)據(jù)傳給組件B,然后組件B再用props傳給組件C,這是一種解決方案,但是如果嵌套的組件過多,就會導致代碼冗余且繁瑣,維護就比較困難,而且如果組件C也要將數(shù)據(jù)傳給組件A,也要一層一層往上傳遞,就更麻煩了
- 自定義一個Vue數(shù)據(jù)總線,這種適合組件跨級傳遞數(shù)據(jù),但是缺點是碰到多人合作時,會導致代碼的維護性較低,代碼可讀性也較低
- 還有一種解決方案,就是用provide inject,但是這種方式,官方不推薦,因為這個方法真的是太不好管控了,比如說我在根組件provide了this,孫孫重孫組件去使用了this里面的一個變量,這時候很難去跟蹤到這個變量的出處了,而且你也并不知道,項目中哪個組件有用到這個變量,有沒有在其他組件中進行改變,所以這個api在項目中很少人使用,但是很多人拿來寫組件用
在很多開發(fā)情況下,我們只是想把組件A的數(shù)據(jù)傳給組件C,如果用props來進行組件通信的話,雖然可以實現(xiàn),但是代碼可讀性上不強,且難維護。
所以這時候,我們的主角$attrs 和 $listeners 就出現(xiàn)了
$attrs 和 $listeners 的用法
在vue2.4中,為了解決該需求,引入了$attrs 和$listeners, 新增了inheritAttrs 選項。 在版本2.4以前,默認情況下父作用域的不被認作props的屬性屬性百年孤獨,將會“回退”且作為普通的HTML特性應用在子組件的根元素上。如下列的例子
父組件的代碼:
<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>我們先看一下這樣寫的時候,控制臺打印出來的dom結構是這樣的:

在2.4中新增選項inheritAttrs,inheritAttrs的默認值為true, 將inheritAttrs的值設為false, 這些默認的行為會禁止掉。但是通過實例屬性 $attrs ,可以將這些特性生效,且可以通過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>然后在加一個孫組件
<template>
<div>
<p>bar:{{ bar }}</p>
</div>
</template>
?
<script>
export default {
props: ["bar"],
};
</script>頁面顯示如下:

從上面的代碼,可以看出使用$attrs ,inheritAttrs 屬性能夠使用簡潔的代碼,將組件A的數(shù)據(jù)傳遞給 組件C,該場景的使用范圍還是挺廣的。
那我們現(xiàn)在來看看組件C怎么傳值給組件A?
vue2.4版本新增了$listeners 屬性,我們在組件B上 綁定 v-on=”$listeners”, 在組件A中,監(jiān)聽組件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>運行結果:

現(xiàn)在我們應該清楚了$attrs,$listerners,inheritAttrs 的作用了吧
到此這篇關于vue $attrs和$listeners的使用與區(qū)別的文章就介紹到這了,更多相關vue $attrs $listeners內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解決vue axios跨域 Request Method: OPTIONS問題(預檢請求)
這篇文章主要介紹了解決vue axios跨域 Request Method: OPTIONS問題(預檢請求),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
VUE 實現(xiàn)element upload上傳圖片到阿里云
這篇文章主要介紹了VUE 實現(xiàn)element upload上傳圖片到阿里云,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
Vue3中Vuex狀態(tài)管理學習實戰(zhàn)示例詳解
這篇文章主要為大家介紹了Vue3中Vuex狀態(tài)管理學習實戰(zhàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06

