Vue中的$attrs和$listener
大家在組件開發中肯定遇到過父組件需要向子組件傳遞數據和事件的問題,以往我們是這樣解決的:
父組件代碼:
1 <template> 2 <div id="father"> 3 <child :tempdata="temp" @fatherFn="tempFn"><child> 4 </div> 5 </template> 6 <script> 7 export default { 8 data() { 9 temp: 'click here!' 10 }, 11 method: { 12 tempFn: function(message) { 13 console.log(message); 14 } 15 } 16 } 17 </script>
子組件代碼:
1 <template> 2 <div id="child"> 3 <span @click="childClick(message)">{{ tempdata }}</span> 4 </div> 5 </template> 6 <script> 7 export default { 8 props: { 9 tempdata: { 10 type: String, 11 default: '' 12 } 13 }, 14 data() { 15 return { 16 message: 'i am child' 17 } 18 }, 19 methods: { 20 childClick: function(message) { 21 this.$emit('fatherFn', message); 22 } 23 } 24 } 25 </script>
這樣我們完成了從父組件傳遞數據已經方法到子組件,但是如果是向子組件的子組件傳遞信息呢?顯然我們需要換一種更加簡單的方式實現祖孫組件之間的數據傳輸,小二上代碼:
1 // father組件 2 <template> 3 <div id="father"> 4 <child :temp="tempdata" @tempFn="fatherFn" prop='$attrs不會傳遞child組件中定義的props 5 值'> 6 </child> 7 </div> 8 </template> 9 <script> 10 import Child from './child' 11 export default { 12 component: { Child }, 13 data() { 14 tempdata: 'i am father' 15 }, 16 methods: { 17 fatherFn: function() { 18 console.log('father function!'); 19 } 20 } 21 } 22 </script> 23 24 // child組件 25 <template> 26 <div id="child"> 27 <son v-bind="$attrs" v-on="$listener"></son> 28 </div> 29 </template> 30 <script> 31 import Son from './son' 32 export default { 33 component: {Son}, 34 props: { 'prop' }, 35 data() { 36 return {} 37 }, 38 mounted() { 39 // 結果顯示為$attrs.temp,不包含prop 40 console.log(this.$attrs) 41 this.$emit('tempFn') 42 }, 43 methods: {} 44 } 45 </script> 46 47 // son組件 48 <template> 49 <div id="son"> 50 {{ $attrs.temp }} 51 </div> 52 </template> 53 <script> 54 export default { 55 prop: {}, 56 data() { 57 return {} 58 }, 59 mounted() { 60 this.$emit('tempFn') 61 }, 62 methods: {} 63 } 64 </script>
綜上,可知:
$listeners包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監聽器,它可以通過 v-on=”$listeners” 傳入內部組件。
$attrs包含了父作用域中非props 特性綁定的屬性 (class 和 style 除外)。當一個組件沒有聲明任何 props 時,這里會包含所有父作用域的綁定 (class 和 style 除外),並且可以通過 v-bind=”$attrs” 傳入內部組件。
--------------------------------------
新增理解
其實$attrs,$listeners,$props都是一樣的,我們可以通過當前組件實例訪問到,具體包含如下:
$attrs:當前組件的屬性,通俗的講也就是在組件標簽定義的一系列屬性,如input的value,placeholder等,但是不包括在當前組件里面定義的props屬性
$listeners:當前組件監聽的事件,通俗的講也就是在使用組件的時候在標簽中定義的事件,如@input,以及一些自定義事件@tempFn等
$props:當前組件從父組件那里接收的參數,通俗的講和$attr差不多,但是只包括在當前組件中定義了的props屬性
通俗的講$attrs+$props = 在使用組件時定義的所有屬性,不包括事件
那么在當前組件中使用v-bind="$attrs",v-bind="$props",v-on="$listeners"也就是把之前父組件那里給它的屬性再全部傳到它的子組件。