vue組件之間通信,我們可以使用props和vuex兩種方式,但是vuex太重,props在多級組件中使用又太麻煩,vue2.4版本提供了另一種方法,使用v-bind="$attrs",將父組件中不被認為 props特性綁定的屬性傳入子組件中,通常配合 interitAttrs 選項一起使用。
例如下面的層級關系
<top>
<center>
<bottom>
</bottom>
</center>
</parent>
如果top組件要和bottom組件進行通信,下面有三種方式可以實現
1.通過props和$emit的方式,需要通過center作為中轉,top把值傳給center,center再把值傳給bottom,或者bottom把值傳給center,center在傳給top
2.使用vuex,但是這兩個組件的狀態可能不是全局狀態
3.使用中央事件總線bus
使用前兩種方式可能都不太理想,這里來講一下另一種方式
先看一下代碼片段
top組件,傳遞了name,age,gender,sdf四個屬性到子組件center,然后接收了兩個isClick()和asd()方法
<template>
<section>
<centers name="name" age="18" gender="666" sdf="asd" @isClick="isClick" @asd="asd"
></centers>
</section>
</template>
<script> import centers from '~/components/center'; export default { components: { centers }, methods: { asd() { console.log(999); }, isClick() { console.log(666); } } }; </script>
center組件,只接收了name和age兩個屬性,其他屬性沒有接收,使用 v-bind="$attrs" 屬性,vm.$attrs
是一個屬性,其包含了父作用域中不作為 prop 被識別 (且獲取) 的特性綁定 (class 和 style 除外)。這些未識別的屬性可以通過 v-bind="$attrs"
傳入內部組件。未識別的事件可通過v-on="$listeners"
傳入(.native綁原生事件是沒用的)。
<template>
<section>
<div class="mt-10">
<bottom v-bind="$attrs" v-on="$listeners" />
</div>
</section>
</template>
<script> import bottom from '~/components/bottom'; export default { components: { bottom }, props: { name: { type: String, default: 'default' }, age: { type: String, default: 'default' } } }; </script>
bottom組件,我們只接收了gender屬性,但是這個屬性是其父組件center使用 v-bind="$attrs" 從top組件接收到的,center組件本身並沒有使用props接收這個屬性,但是bottom屬性確可是使用
<template>
<section>
<div> {{ $attrs['gender'] }} 在$attrs里面只會有props沒有注冊的屬性 <br> {{ gender }} </div>
</section>
</template>
<script> export default { props: { gender: { type: String, default: '' } }, mounted() { console.log(this.$attrs); console.log(this.$listeners); this.$listeners.isClick(); this.$listeners.asd(); } }; </script>
總結
1.v-bind="$props": 可以將父組件的所有props下發給它的子組件,子組件需要在其props:{} 中定義要接受的props。
vm.$props: 當前組件接收到的 props 對象。Vue 實例代理了對其 props 對象屬性的訪問。
2.v-bind="$attrs": 將調用組件時的組件標簽上綁定的非props的特性(class和style除外)向下傳遞。在子組件中應當添加inheritAttrs: false(避免父作用域的不被認作props的特性綁定應用在子組件的根元素上)。
vm.$attrs
:包含了父作用域中不作為 prop 被識別 (且獲取) 的特性綁定 (class 和 style 除外)。當一個組件沒有聲明任何 prop 時,這里會包含所有父作用域的綁定 (class 和 style 除外),並且可以通過 v-bind="$attrs" 傳入內部組件——在創建高級別的組件時非常有用。
3.v-on="將父組件標簽上的自定義事件向下傳遞其子組件可以直接通過emit(eventName)的方式調用。
vm.$listeners
: 包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監聽器。它可以通過 v-on="$listeners" 傳入內部組件——在創建更高層次的組件時非常有用。
4.舉例說明:
4.1.如上實例代碼中,top組件傳值給center可以全部不接收,然后直接通過 v-bind="$attrs" 傳給bottom,然后bottom組件直接使用props接收top傳過來的所有屬性
4.2.在別人組件的基礎上進行二次封裝的時候,定義好自己的屬性,然后在自己的組件上直接傳值,然后通過 v-bind="$attrs" 把值傳給別人的組件即可,例如
<template>
<div>
<el-button v-bind="$attrs">確定</el-button>
<div>
</template> // 父組件使用 <my-button type='primary' size='mini'/>
5.vm.$attrs和vm.$listeners獲取到的值都是json的形式,對應每一個屬性和取值,可以直接使用實例驗證一下~
嗯,就醬~~~