标准答案

  1. attrs 表示父组件传入但没有被 props 或 emits 声明消费的属性,例如 class、style、id、aria-*、data-* 和部分事件监听。
  2. emits 用来声明组件会触发哪些事件。声明后,对应监听不会再作为普通 attrs 透传。
  3. inheritAttrs 默认是 true,未消费的 attrs 会自动透传到组件根节点。设置为 false 后,可以手动用 v-bind="$attrs" 绑定到指定元素。
  4. Vue 2 中 attrs 和 listeners 是分开的;Vue 3 中 listeners 被合并进 attrs,事件会以 onClick、onUpdate:modelValue 这类形式出现。
  5. 二次封装组件时,要明确外部属性应该落到哪个真实元素上,避免把 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,导致组件事件和原生事件透传边界不清楚。

作者信息