多級組件嵌套需要傳遞數據時,通常使用的方法是通過vuex。如果僅僅是傳遞數據,而不做中間處理,使用 vuex 處理,這就有點大材小用了。所以就有了 $attrs / $listeners ,通常配合 inheritAttrs 一起使用。
inheritAttrs:默認值為 true。
默認情況下父作用域的不被認作 props 的 attribute 綁定 (attribute bindings) 將會“回退”且作為普通的 HTML attribute 應用在子組件的根元素上。當撰寫包裹一個目標元素或另一個組件的組件時,這可能不會總是符合預期行為。通過設置
inheritAttrs到false,這些默認行為將會被去掉。而通過 (同樣是 2.4 新增的) 實例 property$attrs可以讓這些 attribute 生效,且可以通過v-bind顯性的綁定到非根元素上。查 看 官 網
感覺還是挺晦澀難懂的,簡單的說就是
$listeners
father.vue 組件:
<template> <child :name="name" :age="age" :infoObj="infoObj" @updateInfo="updateInfo" @delInfo="delInfo" /> </template> <script> import Child from '../components/child.vue' export default { name: 'father', components: { Child }, data () { return { name: 'Lily', age: 22, infoObj: { from: '上海', job: 'policeman', hobby: ['reading', 'writing', 'skating'] } } }, methods: { updateInfo() { console.log('update info'); }, delInfo() { console.log('delete info'); } } } </script>
child.vue 組件:
<template>
<grand-son :height="height" :weight="weight" @addInfo="addInfo" v-bind="$attrs" v-on="$listeners" />
// 通過 $listeners 將父作用域中的事件,傳入 grandSon 組件,使其可以獲取到 father 中的事件
</template>
<script>
import GrandSon from '../components/grandSon.vue'
export default {
name: 'child',
components: { GrandSon },
props: ['name'],
data() {
return {
height: '180cm',
weight: '70kg'
};
},
created() {
console.log(this.$attrs);
// 結果:age, infoObj, 因為父組件共傳來name, age, infoObj三個值,由於name被 props接收了,所以只有age, infoObj屬性
console.log(this.$listeners); // updateInfo: f, delInfo: f
},
methods: {
addInfo () {
console.log('add info')
}
}
}
</script>
grandSon.vue 組件:
<template>
<div>
{{ $attrs }} --- {{ $listeners }}
<div>
</template>
<script>
export default {
... ...
props: ['weight'],
created() {
console.log(this.$attrs); // age, infoObj, height
console.log(this.$listeners) // updateInfo: f, delInfo: f, addInfo: f
this.$emit('updateInfo') // 可以觸發 father 組件中的updateInfo函數
}
}
</script>
這種方式的傳值對我來說不常用,感覺可讀性不是很好。但其對於組件層級嵌套比較深,使用props會很繁瑣,或者項目比較小,不太適合使用 Vuex 的時候,可以考慮用它。
