vue中的$attrs和$listeners


多級組件嵌套需要傳遞數據時,通常使用的方法是通過vuex。如果僅僅是傳遞數據,而不做中間處理,使用 vuex 處理,這就有點大材小用了。所以就有了 $attrs / $listeners ,通常配合 inheritAttrs 一起使用。

 

inheritAttrs:默認值為 true。

默認情況下父作用域的不被認作 props 的 attribute 綁定 (attribute bindings) 將會“回退”且作為普通的 HTML attribute 應用在子組件的根元素上。當撰寫包裹一個目標元素或另一個組件的組件時,這可能不會總是符合預期行為。通過設置 inheritAttrsfalse,這些默認行為將會被去掉。而通過 (同樣是 2.4 新增的) 實例 property $attrs 可以讓這些 attribute 生效,且可以通過 v-bind 顯性的綁定到非根元素上。查 看 官 網

感覺還是挺晦澀難懂的,簡單的說就是 inheritAttrs:true 繼承除props之外的所有屬性;inheritAttrs:false 只繼承class屬性。

 

$attrs:包含了父作用域中不被認為 (且不預期為) props 的特性綁定 (class 和 style 除外),並且可以通過 v-bind=”$attrs” 傳入內部組件。當一個組件沒有聲明任何 props 時,它包含所有父作用域的綁定 (class 和 style 除外)。

$listeners:包含了父作用域中的 (不含 .native 修飾符) v-on 事件監聽器。它可以通過 v-on=”$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 的時候,可以考慮用它。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM