标准答案
- attrs 表示父组件传入但没有被 props 或 emits 声明消费的属性,例如 class、style、id、aria-*、data-* 和部分事件监听。
- emits 用来声明组件会触发哪些事件。声明后,对应监听不会再作为普通 attrs 透传。
- inheritAttrs 默认是 true,未消费的 attrs 会自动透传到组件根节点。设置为 false 后,可以手动用 v-bind="$attrs" 绑定到指定元素。
- Vue 2 中 attrs 和 listeners 是分开的;Vue 3 中 listeners 被合并进 attrs,事件会以 onClick、onUpdate:modelValue 这类形式出现。
- 二次封装组件时,要明确外部属性应该落到哪个真实元素上,避免把 aria、disabled、class 或点击事件透传到错误节点。
题目解析
这题常出现在组件库封装和 Element Plus 二次封装里。真正考点是透传边界。
emits 不只是类型声明,也会影响事件监听是否进入 attrs。
多根节点组件不会自动决定 attrs 落到哪里,需要开发者显式绑定,否则容易出现警告或属性丢失。
代码示例
封装输入框时,可以关闭自动继承,把 attrs 明确透传到 input。
Vue
<script setup lang="ts">
defineOptions({
inheritAttrs: false
})
defineProps<{
label: string
}>()
</script>
<template>
<label class="field">
<span>{{ label }}</span>
<input v-bind="$attrs">
</label>
</template>常见误区
- 封装组件时不管 attrs,导致 class、aria-label、disabled 没有落到真正交互元素上。
- Vue 3 中继续按 Vue 2 的 $listeners 理解事件透传。
- 没有声明 emits,导致组件事件和原生事件透传边界不清楚。