Skip to content

Події компонентів

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

Випромінювання та прослуховування подій

Компонент може випромінювати спеціальні події безпосередньо у виразах шаблону (наприклад, в обробнику v-on), використовуючи вбудований метод $emit:

template
<!-- MyComponent -->
<button @click="$emit('someEvent')">натиснути</button>

Метод $emit() також доступний в екземплярі компонента як this.$emit():

js
export default {
  methods: {
    submit() {
      this.$emit('someEvent')
    }
  }
}

Батьки можуть прослуховувати це за допомогою v-on:

template
<MyComponent @some-event="callback" />

Модифікатор .once також підтримується слухачами подій компонентів:

template
<MyComponent @some-event.once="callback" />

Подібно до компонентів і атрибутів, імена подій забезпечують автоматичне перетворення регістру. Зауважте, що ми створили подію camelCase, але можемо прослухати її за допомогою kebab-case слухача у батьківських компонентах. Як і у випадку з регістром імені реквізиту, ми радимо використовувати в шаблонах прослуховувачі подій kebab-case.

TIP

На відміну від нативних подій DOM, події, створені компонентом, не випливають. Ви можете прослуховувати лише події, які випромінює прямий дочірній компонент. Якщо є потреба в спілкуванні між братськими або глибоко вкладеними компонентами, використовуйте зовнішню шину подій або глобальне рішення для керування станом.

Аргументи події

Іноді корисно випромінювати конкретне значення з подією. Наприклад, ми можемо захотіти, щоб компонент <BlogPost> відповідав за те, на скільки збільшити текст. У таких випадках ми можемо передати додаткові аргументи в $emit, щоб надати це значення:

template
<button @click="$emit('increaseBy', 1)">
  Збільшити на 1
</button>

Тоді, коли ми прослуховуємо подію в батьківському компоненті, ми можемо використовувати вбудовану функцію-стрілку як прослуховувач, що дозволяє отримати доступ до аргументу події:

template
<MyButton @increase-by="(n) => count += n" />

Або, якщо обробником події є метод:

template
<MyButton @increase-by="increaseCount" />

Тоді значення буде передано як перший параметр цього методу:

js
methods: {
  increaseCount(n) {
    this.count += n
  }
}
js
function increaseCount(n) {
  count.value += n
}

TIP

Усі додаткові аргументи, передані в $emit() після назви події будуть перенаправлені слухачу. Наприклад, за допомогою $emit('foo', 1, 2, 3) функція слухача отримає три аргументи.

Оголошення переданих подій

Компонент може явно оголосити події, які будуть випромінюватись за допомогою макросу defineEmits()параметр emits:

vue
<script setup>
defineEmits(['inFocus', 'submit'])
</script>

Метод $emit, який ми використовували в <template>, недоступний у розділі <script setup> компонента, але defineEmits() повертає еквівалентну функцію, яку ми можемо натомість використати:

vue
<script setup>
const emit = defineEmits(['inFocus', 'submit'])

function buttonClick() {
  emit('submit')
}
</script>

Макрос defineEmits() не можна використовувати всередині функції, його потрібно розмістити безпосередньо в <script setup>, як у прикладі вище.

Якщо ви використовуєте явну функцію setup замість <script setup>, події слід оголошувати за допомогою опції emit і emit функція доступна в контексті setup():

js
export default {
  emits: ['inFocus', 'submit'],
  setup(props, ctx) {
    ctx.emit('submit')
  }
}

Як і інші властивості контексту setup(), emit можна безпечно деструктурувати:

js
export default {
  emits: ['inFocus', 'submit'],
  setup(props, { emit }) {
    emit('submit')
  }
}
js
export default {
  emits: ['inFocus', 'submit']
}

Параметр emits і макрос defineEmits() також підтримують синтаксис об’єкта. Якщо ви використовуєте TypeScript, ви можете вводити аргументи, що дозволяє нам виконувати перевірку під час виконання корисного навантаження випущених подій:

vue
<script setup>
const emit = defineEmits({
  submit(payload: { email: string, password: string }) {
    // повертає `true` або `false`, щоб вказати,
    // що перевірка пройшла/не пройшла
  }
})
</script>

Якщо ви використовуєте TypeScript з <script setup>, також можна оголосити події за допомогою суто анотацій:

vue
<script setup lang="ts">
const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
</script>

Детальніше: типізація події компонентів

js
export default {
  emits: {
    submit(payload: { email: string, password: string }) {
      // повертає `true` або `false`, щоб вказати,
      // що перевірка пройшла/не пройшла
    }
  }
}

Дивіться також: типізація події компонентів

Незважаючи на те, що це необов’язково, рекомендується визначати всі випромінювані події, щоб краще задокументувати, як має працювати компонент. Це також дозволяє Vue виключати відомих слухачів із прохідних атрибутів, уникаючи крайніх випадків, спричинених подіями DOM, які вручну випромінюються стороннім кодом.

TIP

Якщо власну подію (наприклад, click) визначено в параметрі emits, слухач тепер стежитиме лише за подіями click, що випромінюються компонентом, і більше не відповідатиме на власні події click.

Перевірка подій

Подібно до перевірки типу реквізитів, подію можна перевірити, якщо її визначено за допомогою синтаксису об’єкта, а не синтаксису масиву.

Щоб додати перевірку, події призначається функція, яка отримує аргументи, передані в this.$emitemit викликає і повертає логічне значення, щоб вказати, подія дійсна чи ні.

vue
<script setup>
const emit = defineEmits({
  // Без перевірки
  click: null,

  // Перевірка події надсилання
  submit: ({ email, password }) => {
    if (email && password) {
      return true
    } else {
      console.warn('Недійсні данні події надсилання!')
      return false
    }
  }
})

function submitForm(email, password) {
  emit('submit', { email, password })
}
</script>
js
export default {
  emits: {
    // Без перевірки
    click: null,

    // Перевірка події надсилання
    submit: ({ email, password }) => {
      if (email && password) {
        return true
      } else {
        console.warn('Недійсні данні події надсилання!')
        return false
      }
    }
  },
  methods: {
    submitForm(email, password) {
      this.$emit('submit', { email, password })
    }
  }
}

Події як реквізити

Ви також можете оголосити та передати events як props, додавши on перед назвою події з великої літери.

Використання props.onEvent має іншу поведінку, ніж використання emit('event'), оскільки перше передасть лише обробку прослухувача на основі властивості (@event або :on-event).

WARNING

Якщо передано і :onEvent, і @event, props.onEvent може бути масивом функцій замість функції, така поведінка не є стабільною та може змінитися в майбутньому.

Через це рекомендується використовувати emit('event') замість props.onEvent під час випромінювання подій.

Події компонентів has loaded