Атрибуты: $attrs и inheritAttrs

↑ 4.1 Vue 3: основы, компоненты, Composition API · ← Предыдущая · → Следующая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

Как проксировать атрибуты и события через обёртки над нативными элементами и UI-компонентами.

Объяснение

Fallthrough attributes: атрибуты и обработчики, переданные компоненту, но не объявленные как props/emits, автоматически применяются к корневому элементу (class, style — объединяются).

<!-- MyInput.vue: корень — label, а нативный input нужно получить атрибуты -->
<script setup>
defineOptions({ inheritAttrs: false });          // отключить автопрокидывание на корень
const attrs = useAttrs();
</script>
<template>
  <label class="field">
    <span>{{ label }}</span>
    <input v-bind="$attrs" />                     <!-- placeholder, type, @focus, class... попадают на input -->
  </label>
</template>
 
<MyInput label="Имя" placeholder="Введите" type="text" @focus="log" class="wide" />
ПонятиеОписание
$attrs / useAttrs()неobъявленные props + атрибуты + обработчики событий (в Vue 3 class, style и слушатели входят в $attrs)
inheritAttrs: falseотключает автоприменение к корню
v-bind="$attrs"ручное проксирование на нужный элемент
Несколько корнейнет автопрокидывания: нужно явно v-bind="$attrs", иначе предупреждение

Применение: обёртки над нативными и UI-библиотечными компонентами (кастомизация Quasar QInput с сохранением всех его props и слотов).

<q-input v-bind="{ ...$attrs, ...defaults }">
  <template v-for="(_, slot) in $slots" #[slot]="scope"><slot :name="slot" v-bind="scope ?? {}" /></template>
</q-input>

Vue 3 отличия от Vue 2: $listeners удалён (слушатели внутри $attrs), class/style тоже.

Нюансы и подводные камни

  • $attrs не реактивен для watch в Options API (используйте onUpdated) — в Composition API useAttrs() даёт актуальные значения, но не отслеживается напрямую.
  • Порядок слияния: v-bind="$attrs" до/после других атрибутов определяет приоритет.
  • Не забывайте прокидывать слоты при обёртке.
  • Неявное применение атрибутов на корень может быть неожиданным.

Практика

  1. Сделайте обёртку BaseInput, проксирующую атрибуты и события на <input>.
  2. Оберните Quasar q-input с общими настройками и прокидыванием слотов.
  3. Проверьте слияние class и style.

Вопросы с ответами

Связанные темы