# Передача обычных атрибутов
Подразумевается, что уже изучили и разобрались с разделом Основы компонентов. Если нет — прочитайте его сначала.
Обычный атрибут для компонента — атрибут или слушатель события, который передаётся в компонент, но не имеет соответствующего свойства указанного в props или emits. Частыми примерами подобного являются атрибуты class
, style
и id
. Доступ к этим атрибутам можно получить через свойство $attrs
.
# Наследование атрибутов
Если в компоненте один корневой элемент, то обычные атрибуты будут добавляться к этому элементу автоматически. Например, для экземпляра компонента выбора даты:
app.component('date-picker', {
template: `
<div class="date-picker">
<input type="datetime-local" />
</div>
`
})
2
3
4
5
6
7
Если потребуется определять статус компонента выбора даты через атрибут data-status
, значение будет добавлено к корневому элементу (т.е. к div.date-picker
).
<!-- Компонент выбора даты с обычным атрибутом -->
<date-picker data-status="activated"></date-picker>
<!-- Отрисованный компонент выбора даты -->
<div class="date-picker" data-status="activated">
<input type="datetime-local" />
</div>
2
3
4
5
6
7
Аналогично правило применяется и для обработчиков событий:
<date-picker @change="submitChange"></date-picker>
app.component('date-picker', {
created() {
console.log(this.$attrs) // { onChange: () => {} }
}
})
2
3
4
5
Это удобно, когда корневым элементом компонента date-picker
будет HTML-элемент, генерирующий событие change
.
app.component('date-picker', {
template: `
<select>
<option value="1">Вчера</option>
<option value="2">Сегодня</option>
<option value="3">Завтра</option>
</select>
`
})
2
3
4
5
6
7
8
9
Обработчик события change
будет передан из родительского компонента в дочерний и станет вызываться при нативном событии change
на корневом элементе <select>
. При таком подходе не потребуется явно генерировать событие внутри date-picker
:
<div id="date-picker" class="demo">
<date-picker @change="showChange"></date-picker>
</div>
2
3
const app = Vue.createApp({
methods: {
showChange(event) {
console.log(event.target.value) // выведет значение выбранного варианта
}
}
})
2
3
4
5
6
7
# Отключение наследования атрибутов
При необходимости отключить автоматическое наследование обычных атрибутов компонентом это можно сделать с помощью опции inheritAttrs: false
.
Популярная причина, когда требуется отключать наследование атрибутов — необходимость добавления атрибутов на другой элемент вместо корневого.
Установив опцию inheritAttrs
в false
, добавлять атрибуты к выбранному элементу можно с помощью свойства $attrs
, в нём будут все атрибуты, не указанные в свойствах props
и emits
(например, class
, style
, обработчики v-on
, и т.д.).
Используя компонент для выбора дат из предыдущей главы, изменим добавление обычных атрибутов на элемент input
, вместо корневого элемента div
. Для этого воспользуемся сокращённой записью v-bind
:
app.component('date-picker', {
inheritAttrs: false,
template: `
<div class="date-picker">
<input type="datetime-local" v-bind="$attrs" />
</div>
`
})
2
3
4
5
6
7
8
В таком случае обычный атрибут data-status
будет добавляться на элемент input
!
<!-- Компонент выбора даты с обычным атрибутом -->
<date-picker data-status="activated"></date-picker>
<!-- Отрисованный компонент выбора даты -->
<div class="date-picker">
<input type="datetime-local" data-status="activated" />
</div>
2
3
4
5
6
7
# Наследование атрибутов при нескольких корневых элементах
В отличие от компонентов с одним корневым элементом, для компонентов с несколькими корневыми элементами не будет автоматического наследования атрибутов. Если $attrs
не привязать к элементу явно, то это приведёт к предупреждению во время выполнения.
<custom-layout id="custom-layout" @click="changeValue"></custom-layout>
// НЕПРАВИЛЬНО, будет выведено предупреждение
app.component('custom-layout', {
template: `
<header>...</header>
<main>...</main>
<footer>...</footer>
`
})
// ПРАВИЛЬНО, $attrs передаются на элемент <main>
app.component('custom-layout', {
template: `
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
`
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17