Vue 新增的$attrs與$listeners的詳解

名詞解釋

inheritAttrs:默認值true,繼承全部的父組件屬性(除props的特定綁定)做爲普通的HTML特性應用在子組件的根元素上,若是你不但願組件的根元素繼承特性設置inheritAttrs: false,可是class屬性會繼承(簡單的說,inheritAttrs:true 繼承除props以外的全部屬性;inheritAttrs:false 只繼承class屬性javascript

$attrs--繼承全部的父組件屬性(除了prop傳遞的屬性、class 和 style ),通常用在子組件的子元素上,如第一個例子的<input v-bind="$attrs"/>html

$listeners--屬性,它是一個對象,裏面包含了做用在這個組件上的全部監聽器,你就能夠配合 v-on="$listeners" 將全部的事件監聽器指向這個組件的某個特定的子元素。(至關於子組件繼承父組件的事件前端

主要用途

用在父組件傳遞數據給子組件或者孫組件vue

例1java

<body class="">
    <div id="app" class="demo">
        <base-input label="姓名" class="username-input" placeholder="Enter your username" data-date-picker="activated"></base-input>
    </div>
    <script src="js/vue-2.5.13.js"></script>
    <script>
    Vue.component("base-input", {
        inheritAttrs: false, //此處設置禁用繼承特性 (只繼承class屬性)
        props: ["label"],
        template: `
        <label>
          {{label}}
          {{$attrs.placeholder}}
          {{$attrs["data-date-picker"]}}
          <input v-bind="$attrs"/>
        </label>
        `,
        mounted: function() {
            console.log(this.$attrs);
        }
    })
    const app = new Vue({
        el: '#app',
        data: {

        }

    });
  
    </script>
</body>

上面的例子渲染後的HTML以下:微信

<label class="username-input">
    姓名 
    Enter your username 
    activated
    <input placeholder="Enter your username" data-date-picker="activated">
</label>

若是把上面例子中的inheritAttrs: false去掉或者改成inheritAttrs: true,最終渲染爲:app

<label placeholder="Enter your username" data-date-picker="activated" class="username-input">
    姓名
    Enter your username
    activated
    <input placeholder="Enter your username" data-date-picker="activated">
</label>

同時子組件能夠單獨使用$attrs,如上面的{{$attrs.placeholder}}依然是繼承父組件的placeholder屬性網站

例2:假設有三個組件A組件包含B,B組件包含C組件this

A組件(App.vue)
<template>
    <div id="app">
        <child1 :p-child1="child1" :p-child2="child2" v-on:test1="onTest1" //此處監聽了兩個事件,能夠在B組件或者C組件中直接觸發 v-on:test2="onTest2">
        </child1>
    </div>
</template>
<script>
import Child1 from './Child1.vue';
export default {
    data() {
        return {};
    },
    components: { Child1 },
    methods: {
        onTest1() {
            console.log('test1 running...');
        },
        onTest2() {
            console.log('test2 running');
        }
    }
};
</script>

B組件(Child1.vue)
<template>
    <div class="child-1">
        <p>in child1:</p>
        <p>props: {{pChild1}}</p>
        <p>$attrs: {{$attrs}}</p>
        <hr>
        <!-- C組件中能直接觸發test的緣由在於 B組件調用C組件時 使用 v-on 綁定了$listeners 屬性 -->
        <!-- 經過v-bind 綁定$attrs屬性,C組件能夠直接獲取到A組件中傳遞下來的props(除了B組件中props聲明的) -->
        <child2 v-bind="$attrs" v-on="$listeners"></child2>
    </div>
</template>
<script>
import Child2 from './Child2.vue';
export default {
    props: ['pChild1'],
    data() {
        return {};
    },
    inheritAttrs: false,
    components: { Child2 },
    mounted() {
        this.$emit('test1');
    }
};
</script>

C 組件 (Child2.vue)
<template>
    <div class="child-2">
        <p>in child2:</p>
        <p>props: {{pChild2}}</p>
        <p>$attrs: {{$attrs}}</p>
        <hr>
    </div>
</template>
<script>
export default {
    props: ['pChild2'],
    data() {
        return {};
    },
    inheritAttrs: false,
    mounted() {
        this.$emit('test2');
    }
};
</script>

個人我的網站-前端之攻略spa

微信號:前端之攻略

相關文章
相關標籤/搜索