Vue中$attrs和$listeners詳解以及使用方法
- 傳送門:Vue中 子組件向父組件傳值 及 .sync 修飾符 詳解
- 傳送門:Vue中 狀態(tài)管理器(vuex)詳解及應用場景
- 傳送門:Vue中 事件總線(eventBus)詳解及使用
- 傳送門:Vue中 provide、inject 詳解及使用
Vue中 常見的組件通信方式可分為三類
父子通信
父向子傳遞數(shù)據(jù)是通過 props,子向父是通過 events($emit);
通過父鏈 / 子鏈也可以通信($parent / $children);
ref 也可以訪問組件實例;
provide / inject;
$attrs/$listeners;
兄弟通信
Bus;
Vuex;
跨級通信
Bus;
Vuex;
provide / inject、
$attrs / $listeners、
1. 前言
多級組件嵌套需要傳遞數(shù)據(jù)時,通常使用的方法是通過 vuex。如果僅僅是傳遞數(shù)據(jù),而不做中間處理,使用 vuex 處理,未免有點殺雞用牛刀。
Vue 2.4 版本提供了另一種方法,使用 v-bind=”$attrs”, 將父組件中不被認為 props 特性綁定的屬性傳入子組件中,通常配合 interitAttrs 選項一起使用。之所以要提到這兩個屬性,是因為兩者的出現(xiàn)使得組件之間跨組件的通信在不依賴 vuex 和 事件總線 的情況下變得簡潔,業(yè)務清晰。
首先分析以下應用場景

A 組件與 B 組件之間的通信: (父子組件)
如上圖所示,A、B、C三個組件依次嵌套,按照 Vue 的開發(fā)習慣,父子組件通信可以通過以下方式實現(xiàn):
- A to B 通過 props 的方式向子組件傳遞,B to A 通過在 B 組件中 $emit, A 組件中 v-on 的方式實現(xiàn);
- 通過設置全局 Vuex 共享狀態(tài),通過 computed 計算屬性和 commit mutation 的方式實現(xiàn)數(shù)據(jù)的獲取和更新,以達到父子組件通信的目的;
- Vue Event Bus,使用 Vue 的實例,實現(xiàn)事件的監(jiān)聽和發(fā)布,實現(xiàn)組件之間的傳遞;
往往數(shù)據(jù)在不需要全局的情況而僅僅是父子組件通信時,使用第一種方式即可滿足。
A 組件與 C 組件之間的通信: (跨多級的組件嵌套關系)
如上圖,A 組件與 C 組件之間屬于跨多級的組件嵌套關系,以往兩者之間如需實現(xiàn)通信,往往通過以下方式實現(xiàn):
- 借助 B 組件的中轉,從上到下 props 依次傳遞,從下至上 $emit 事件的傳遞,達到跨級組件通信的效果;
- 借助 Vuex 的全局狀態(tài)共享;
- Vue Event Bus,使用 Vue 的實例實現(xiàn)事件的監(jiān)聽和發(fā)布,實現(xiàn)組件之間的傳遞
第一種通過 props 和 $emit 的方式,使得組件之間的業(yè)務邏輯臃腫不堪,B組件在其中僅僅充當?shù)氖且粋€中轉站的作用;
第二種 Vuex 的方式,某些情況下似乎又有點大材小用的意味(僅僅是想實現(xiàn)組件之間的一個數(shù)據(jù)傳遞,并非數(shù)據(jù)共享的概念);
第三種情況的使用在實際的項目操作中發(fā)現(xiàn),如不能實現(xiàn)很好的事件監(jiān)聽與發(fā)布的管理,往往容易導致數(shù)據(jù)流的混亂,在多人協(xié)作的項目中,不利于項目的維護;
$attrs 以及 $listeners 的出現(xiàn)解決的就是第一種情況的問題,B 組件在其中傳遞 props 以及事件的過程中,不必在寫多余的代碼,
僅僅是將 $attrs 以及 $listeners 向上或者向下傳遞即可。
2. 知識點

inheritAttrs:默認值 true,繼承所有的父組件屬性(除 props 的特定綁定)作為普通的HTML特性應用在子組件的根元素上,如果你不希望組件的根元素繼承特性設置 inheritAttrs: false ,但是 class 屬性會繼承。
(簡單的說,inheritAttrs:true 繼承除 props 之外的所有屬性;inheritAttrs:false 只繼承 class style 屬性)

$attrs–繼承所有的父組件屬性(除了 prop 傳遞的屬性、class 和 style ),一般用在子組件的子元素上

$ listeners屬性,它是一個對象,里面包含了作用在這個組件上的所有監(jiān)聽器,你就可以配合 v-on="$listeners" 將所有的事件監(jiān)聽器指向這個組件的某個特定的子元素。(相當于子組件繼承父組件的事件)
3. 示例
A組件(App.vue)
<template>
<div id="app">
<!-- 此處監(jiān)聽了兩個事件,可以在B組件或者C組件中直接觸發(fā) -->
<child1 :pchild1="child1" :pchild2="child2" :pchild3="child3" @method1="onMethod1" @method2="onMethod2"></child1>
</div>
</template>
<script>
import Child1 from "./Child1.vue";
export default {
data() {
return {
child1:'1',
child2: 2,
child3:{
name:'child3'
}
};
},
components: { Child1 },
methods: {
onMethod1(msg1) {
console.log(`${msg1} running`);
},
onMethod2(msg2) {
console.log(`${msg2} running`);
},
},
};
</script>
B組件(Child1.vue)
<template>
<div class="child-1">
<h2>in child1</h2>
<p>props: {{ pchild1 }}</p>
<p>$attrs: {{ $attrs }}</p>
<hr/>
<!-- 通過 v-bind 綁定$attrs屬性,C組件可以直接獲取到A組件中傳遞下來的props(除了B組件中props聲明的) -->
<!-- C組件中能直接觸發(fā)test的原因在于 B組件調用C組件時 使用 v-on 綁定了$listeners 屬性 -->
<child2 v-bind="$attrs" v-on="$listeners"></child2>
</div>
</template>
<script>
import Child2 from "./Child2.vue";
export default {
data() {
return {
child1:'child1'
};
},
components: { Child2 },
props: {
pchild1:{
type:String
}
},
inheritAttrs: false,
mounted() {
this.$emit("method1",this.child1);
},
};
</script>
C 組件 (Child2.vue)
<template>
<div class="child-2">
<h2>in child2:</h2>
<p>props: {{ pChild2 }}</p>
<p>$attrs: {{ $attrs }}</p>
<p>pchild3Name: {{ $attrs.pchild3.name }}</p>
<hr/>
</div>
</template>
<script>
export default {
data() {
return {
child2:'child2'
};
},
props: {
pChild2:{
type:String,
}
},
inheritAttrs: false,
mounted() {
this.$emit("method2",this.child2);
},
};
</script>
效果

總結
到此這篇關于Vue中$attrs和$listeners詳解及使用的文章就介紹到這了,更多相關Vue $attrs、$listeners詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue中v-model指令與.sync修飾符的區(qū)別詳解
本文主要介紹了vue中v-model指令與.sync修飾符的區(qū)別詳解,詳細的介紹了兩個的用法和區(qū)別,感興趣的可以了解一下2021-08-08
vue在html標簽{{}}中調用函數(shù)的方法總結及對比
這篇文章主要給大家介紹了關于vue在html標簽{{}}中調用函數(shù)的方法總結及對比,文中通過實例代碼介紹的非常詳細,對大家學習或者使用vue具有一定的參考學習價值,需要的朋友可以參考下2023-03-03
vue項目使用typescript創(chuàng)建抽象類及其使用方式
這篇文章主要介紹了vue項目使用typescript創(chuàng)建抽象類及其使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
Vite中使用Ant?Design?Vue3.x框架教程示例
這篇文章主要為大家介紹了Vite中使用Ant?Design?Vue3.x框架教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06

