文章目錄
- 透傳屬性
- 如何禁止“透傳屬性和事件”
- 多根節點設置透傳
- 訪問“透傳屬性和事件”
- `$props`、`$attrs`和`$listeners`的使用詳解
透傳屬性
- 透傳屬性和事件并沒有在子組件中用
props
和emits
聲明 - 透傳屬性和事件最常見的如
@click
和class
、id
、style
- 當子組件只有一個根元素時,透傳屬性和事件會自動添加到該根元素上;如果根元素已有
class
或style
屬性,它會自動合并
如何禁止“透傳屬性和事件”
- 在選項式 API 中,你可以在組件選項中設置
inheritAttrs: false
來阻止; - 在組合式 API 的
<script setup>
中,你需要一個額外的<script>
塊來書寫inheritAttrs: false
選項聲明來禁止
<script>
export default {inheritAttrs: false // 阻止自動透傳給唯一的根組件
}
</script>
多根節點設置透傳
多根節點的組件并沒有自動“透傳屬性和事件”的行為,由于Vue不確定要將“透傳屬性和事件”透傳到哪里,所以我們需要v-bind="$attrs"
來顯式綁定,否則將會拋出一個運行時警告。
<button class="chip" v-bind="$attrs">普通紙片</button>
訪問“透傳屬性和事件”
在選項式 API 中,我們可通過this.$attrs
來訪問“透傳屬性和事件”
在組合式 API 中的<script setup>
中引入useAttrs()
來訪問一個組件的“透傳屬性和事件”
<script setup>
import { useAttrs } from 'vue';// 透傳的屬性和事件對象
let attrs = useAttrs()// 在 JS 中訪問透傳的屬性和事件
function showAttrs() {console.log(attrs)console.log(attrs.class)console.log(attrs.title)console.log(attrs.style)attrs.onClick()
}
</script><template><button class="chip" v-bind="attrs"></button><h6>{{ attrs }}</h6><ul><li>{{ attrs.title }}</li><li>{{ attrs.class }}</li><li>{{ attrs.style }}</li></ul><button @click="attrs.onClick()">執行透傳的事件</button><button @click="showAttrs">在 JS 中訪問透傳的屬性和事件</button>
</template><style>
.chip {border: none;background-color: rgb(231, 231, 231);padding: 8px 15px;margin: 10px;
}.rounded {border-radius: 100px;
}
</style>
$props
、$attrs
和$listeners
的使用詳解
$props
:當前組件接收到的 props 對象。Vue 實例代理了對其 props 對象屬性的訪問。$attrs
:包含了父作用域中不作為 prop 被識別 (且獲取) 的特性綁定 (class 和 style 除外)。$listeners
:包含了父作用域中(不含.native
修飾器的)v-on
事件監聽器。他可以通過v-on="listeners"
傳入內部組件
1、父組件
<template><div><div>父親組件</div><Child:foo="foo":zoo="zoo"@handle="handleFun"></Child></div>
</template><script>
import Child from './Child.vue'
export default {components: { Child },data() {return {foo: 'foo',zoo: 'zoo'}},methods: {// 傳遞事件handleFun(value) {this.zoo = valueconsole.log('孫子組件發生了點擊事件,我收到了')}}
}
</script>
2.兒子組件(Child.vue)
在兒子組件中給孫子組件添加v-bind="$attrs"
,這樣孫子組件才能接收到數據。
$attrs
是從父組件傳過來的,且兒子組件未通過props接收的數據,例如zoo
<template><div class='child-view'><p>兒子組件--{{$props.foo}}與{{foo}}內容一樣</p><GrandChild v-bind="$attrs" v-on="$listeners"></GrandChild></div>
</template><script>
import GrandChild from './GrandChild.vue'
export default {// 繼承所有父組件的內容inheritAttrs: true,components: { GrandChild },props: ['foo'],data() {return {}}
}
</script>
3.孫子組件(GrandChild.vue)
在孫子組件中一定要使用props接收從父組件傳遞過來的數據
<template><div class='grand-child-view'><p>孫子組件</p><p>傳給孫子組件的數據:{{zoo}}</p><button @click="testFun">點我觸發事件</button></div>
</template><script>
export default {// 不想繼承所有父組件的內容,同時也不在組件根元素dom上顯示屬性inheritAttrs: false,// 在本組件中需要接收從父組件傳遞過來的數據,注意props里的參數名稱不能改變,必須和父組件傳遞過來的是一樣的props: ['zoo'],methods: {testFun() {this.$emit('handle', '123')}}
}
</script>