Skip to content

Прохідні атрибути

Ця сторінка передбачає, що ви вже прочитали основи компонентів. Прочитайте це спочатку, якщо ви новачок у компонентах.

Наслідування атрибутів

Прохідний атрибут — це атрибут або v-on слухач подій, який передається компоненту, але не оголошується явно в реквізитах або випромінюваннях приймаючого компонента. Типовими прикладами цього є атрибути class, style та id.

Коли компонент рендерить один кореневий елемент, прохідні атрибути будуть автоматично додані до атрибутів кореневого елемента. Наприклад, задано компонент <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 />

Тоді прохідні атрибути, отримані <MyButton>, будуть автоматично перенаправлені <BaseButton>.

Зауважте:

  1. Перенаправлені атрибути не включають жодних атрибутів, оголошених як реквізити, або v-on слухачів оголошених подій <MyButton> — іншими словами, оголошені атрибути та слухачі були "спожиті" <MyButton>.

  2. Перенаправлені атрибути можуть бути прийняті як реквізити <BaseButton>, якщо вони оголошені ним.

Вимкнення наслідування атрибутів

Якщо ви не хочете, щоб компонент автоматично наслідував атрибути, ви можете встановити inheritAttrs: false у параметрах компонента.

Починаючи з 3.3 ви також можете використовувати defineOptions безпосередньо в <script setup>:

vue
<script setup>
  defineOptions({
    inheritAttrs: false
  })
  // ...логіка налаштування
</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>

Доступ до прохідних атрибутів in 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 під час кожного оновлення.

За потреби ви можете отримати доступ до прохідних атрибутів компонента через властивість екземпляра $attrs:

js
export default {
  created() {
    console.log(this.$attrs)
  }
}
Прохідні атрибути has loaded