Передаваемые атрибуты
Эта страница предполагает, что вы уже прочитали Основы компонентов.
Наследование атрибутов
«Передаваемый атрибут» — атрибут или слушатель v-on
, который передаётся в компонент, но не имеет соответствующего свойства, указанного в props или emits. Примерами подобных атрибутов являются class
, style
и id
.
Примечание переводчика
Термин «fallthrough attributes» в контексте Vue.js и других библиотек JavaScript относится к атрибутам, которые передаются компоненту, но не обрабатываются явно внутри него. Вместо этого они «проваливаются» (или передаются) дальше к корневому элементу компонента. Это позволяет разработчикам использовать стандартные HTML-атрибуты или пользовательские атрибуты, не определяя их в самом компоненте.
Например, если компонент принимает определённые пропсы, но также получает дополнительные атрибуты, которые не были явно указаны, эти дополнительные атрибуты могут быть автоматически добавлены к корневому элементу компонента. Это упрощает работу с компонентами и делает их более гибкими, позволяя использовать их в различных контекстах без необходимости повторного определения всех возможных атрибутов.
Когда компонент отображает один корневой элемент, передаваемые атрибуты будут автоматически добавлены к атрибутам корневого элемента. Например, задан компонент <MyButton>
со следующим шаблоном:
template
<!-- шаблон <MyButton> -->
<button>Нажми меня</button>
И родитель, использующий этот компонент с:
template
<MyButton class="large" />
Окончательный вариант DOM будет выглядеть так:
html
<button class="large">Нажми меня</button>
Здесь <MyButton>
не объявил class
в качестве принимаемого параметра. Поэтому class
рассматривается как передаваемый атрибут и автоматически добавляется к корневому элементу <MyButton>
.
Объединение class
и style
Если корневой элемент дочернего компонента уже имеет существующие атрибуты class
или style
, они будут объединены со значениями class
и style
, унаследованными от родителя. Предположим, мы изменим шаблон <MyButton>
в предыдущем примере на:
template
<!-- шаблон <MyButton> -->
<button class="btn">Нажми меня</button>
Тогда окончательный вид DOM будет выглядеть так:
html
<button class="btn large">Нажми меня</button>
Наследование слушателей v-on
Это же правило действует для слушателей событий v-on
:
template
<MyButton @click="onClick" />
Слушатель click
будет добавлен к корневому элементу <MyButton>
, то есть к собственному элементу <button>
. Когда нажата собственная <button>
, запускается метод onClick
родительского компонента. Если встроенная <button>
уже имеет слушатель click
, связанный с v-on
, то сработают оба слушателя.
Наследование вложенных компонентов
Если компонент отображает другой компонент в качестве своего корневого узла, тогда передаваемые атрибуты, полученные <MyButton>
, будут автоматически переданы <BaseButton>
:
template
<!-- шаблон <MyButton/>, который просто отображает другой компонент -->
<BaseButton />
Обратите внимание, что:
Пересылаемые атрибуты не включают в себя какие-либо атрибуты, объявленные как параметры, или слушатели
v-on
событий, объявленных<MyButton>
— другими словами, объявленные параметры и слушатели были «потреблены»<MyButton>
.Пересылаемые атрибуты могут быть приняты в качестве свойств
<BaseButton>
, если они объявлены им.
Отключение наследования атрибутов
Если вы не хотите, чтобы компонент автоматически наследовал атрибуты, вы можете установить inheritAttrs: false
в опциях компонента.
Начиная с версии 3.3 вы также можете использовать defineOptions
непосредственно в <script setup>
:
vue
<script setup>
defineOptions({
inheritAttrs: false
})
// ...логика setup
</script>
Чаще всего отключение наследования атрибутов происходит, когда атрибуты необходимо применить к другим элементам, помимо корневого узла. Установив опцию inheritAttrs
в значение false
, вы можете полностью контролировать, где должны применяться передаваемые атрибуты.
К этим атрибутам можно обращаться непосредственно в шаблонных выражениях как к $attrs
:
template
<span>Передаваемые атрибуты: {{ $attrs }}</span>
Объект $attrs
включает все атрибуты, которые не объявлены свойствами props
или emits
компонента (например, class
, style
, v-on
слушатели и т. д.).
Примечания:
В отличие от параметров, атрибуты сохраняют исходную оболочку в JavaScript, поэтому к атрибуту типа
foo-bar
нужно обращаться как$attrs['foo-bar']
.Слушатель события
v-on
, например@click
, будет развёрнут в объекте в виде функции$attrs.onClick
.
Используя наш пример компонента <MyButton>
из предыдущего раздела — иногда нам может понадобиться обернуть сам элемент <button>
дополнительным <div>
в целях стилизации:
template
<div class="btn-wrapper">
<button class="btn">Нажми меня</button>
</div>
Мы хотим, чтобы все передаваемые атрибуты, такие как class
и v-on
, применялись к внутреннему <button>
, а не к внешнему <div>
. Мы можем добиться этого с помощью inheritAttrs: false
и v-bind="$attrs"
:
template
<div class="btn-wrapper">
<button class="btn" v-bind="$attrs">Нажми меня</button>
</div>
Помните, что v-bind
без аргумента связывает все свойства объекта как атрибуты целевого элемента.
Наследование атрибутов при нескольких корневых элементах
В отличие от компонентов с одним корневым узлом, компоненты с несколькими корневыми узлами не имеют автоматического поведения для передаваемых атрибутов. Если $attrs
не привязаны явно, будет выдано предупреждение во время выполнения.
template
<CustomLayout id="custom-layout" @click="changeValue" />
Если <CustomLayout>
имеет следующий многокорневой шаблон, будет выдано предупреждение, поскольку Vue не может быть уверен, где применить передаваемые атрибуты:
template
<header>...</header>
<main>...</main>
<footer>...</footer>
Предупреждение будет подавлено, если $attrs
явно привязаны:
template
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
Доступ к передаваемым атрибутам в JavaScript
При необходимости вы можете получить доступ к передаваемым атрибутам компонента в <script setup>
с помощью API useAttrs()
:
vue
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>
Если не использовать <script setup>
, то attrs
будет отображаться как свойство контекста setup()
:
js
export default {
setup(props, ctx) {
// Атрибуты отображаются как ctx.attrs
console.log(ctx.attrs)
}
}
Обратите внимание, что хотя объект attrs
здесь всегда отражает последние передаваемые атрибуты, он не является реактивным (по соображениям производительности). Вы не можете использовать наблюдатели для наблюдения за его изменениями. Если вам нужна реактивность, используйте опору. В качестве альтернативы вы можете использовать onUpdated()
, чтобы выполнять побочные эффекты с последними attrs
при каждом обновлении.