Skip to content

Události komponent (Events)

Tato stránka předpokládá, že už jste četli Základy komponent. Pokud jsou pro vás komponenty nové, přečtěte si je jako první.

Vyvolání událostí a naslouchání jim

Komponenta může vysílat (emit) vlastní události přímo ve výrazech šablony (např. ve v-on handleru) pomocí vestavěné metody $emit:

template
<!-- MyComponent -->
<button @click="$emit('someEvent')">klikni na mě</button>

Metoda $emit() je také dostupná v rámci instance komponenty přes this.$emit():

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

Komponenta rodiče může událostem naslouchat s využitím v-on:

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

Event listenery komponenty podporují i modifikátor .once:

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

Stejně jako komponenty a vlastnosti poskytují názvy událostí automatickou transformaci názvů. Všimněte si, že jsme emitovali událost jako camelCase, ale můžeme jí v komponentě rodiče naslouchat pomocí listeneru s kebab-cased zápisem. Stejně jako v případě velkých a malých písmen v názvech vlastností doporučujeme v šablonách používat kebab-cased event listenery.

TIP

Na rozdíl od nativních DOM událostí, události vysílané komponentou neprobublávají. Můžete naslouchat pouze událostem vysílaným přímo komponentou potomka. Pokud je potřeba komunikovat mezi sourozeneckými nebo hluboce vnořenými komponentami, použijte externí sběrnici událostí (event bus) nebo globální správu stavu.

Parametry událostí

Někdy je užitečné vysílat spolu s událostí určitou hodnotu. Například můžeme chtít, aby komponenta <BlogPost> určovala, o kolik se má zvětšit text. V takových případech můžeme události $emit předat další parametry, které tuto hodnotu poskytnou:

template
<button @click="$emit('increaseBy', 1)">
  Zvýšit o 1
</button>

Když pak nasloucháme události v komponentě rodiče, můžeme jako listener použít inline arrow funkci, která nám umožní přistupovat k parametrům události:

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

Nebo pokud je event handler funkce:

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

Pak bude hodnota předána do této funkce jako první parametr:

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

TIP

Všechny další parametry předané do $emit() za názvem události budou předány do listeneru. Například při $emit('foo', 1, 2, 3) obdrží funkce listeneru tři parametry.

Deklarování vysílaných událostí

Komponenta může explicitně deklarovat události, které bude vysílat, pomocí makra defineEmits()možnosti emits:

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

Metoda $emit, kterou jsme použili v <template>, není v sekci <script setup> komponenty přístupná, ale defineEmits() vrací ekvivalentní funkci, kterou můžeme použít místo ní:

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

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

Makro defineEmits() nemůže být použito uvnitř funkce, musí být umístěno přímo do <script setup> jako ve výše uvedeném případě.

Pokud používáte explicitní funkci setup místo <script setup>, měly by být události deklarovány pomocí možnosti emits a funkce emit je vystavena v kontextu setup():

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

Stejně jako ostatní vlastnosti kontextu setup(), emit může být bezpečně destrukturována:

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

Možnost emits a defineEmits() makro také podporují objektovou syntaxi. Při použití TypeScriptu je možné typovat argumenty, což nám umožňuje provádět runtime validaci obsahu (payload) emitovaných událostí:

vue
<script setup lang="ts">
const emit = defineEmits({
  submit(payload: { email: string, password: string }) {
    // vrací `true` nebo `false` pro určení,
    // zda validace prošla / selhala
  }
})
</script>

Pokud používáte TypeScript dohromady se <script setup>, je také možné deklarovat vysílané události pomocí „pure“ typových anotací:

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

Více detailů: Typování emitovaných událostí komponenty

js
export default {
  emits: {
    submit(payload: { email: string, password: string }) {
    // vrací `true` nebo `false` pro určení,
    // zda validace prošla / selhala
    }
  }
}

Viz také: Typování událostí komponent

Ačkoli to není povinné, doporučuje se definovat všechny vysílané události, aby bylo možné lépe zdokumentovat, jak má komponenta fungovat. Umožňuje to také Vue vyloučit známé listenery z fallthrough atributů, čímž se vyhnete okrajovým případům způsobeným DOM událostmi odesílanými ručně kódem třetí strany.

TIP

Pokud je v možnosti emits definována nativní událost (např. click), bude nyní listener naslouchat pouze událostem click vysílaným komponentou a nebude již reagovat na nativní události click.

Validace událostí

Podobně jako u validace typů u vlastností lze validovat emitovanou událost, pokud je definována pomocí syntaxe objektu namísto syntaxe pole.

Pro přidání validace je události přiřazena funkce, která obdrží parametry předané do volání this.$emitemit a vrátí boolean hodnotu označující, zda je událost platná, nebo ne.

vue
<script setup>
const emit = defineEmits({
  // bez validace
  click: null,

  // validace události `submit`
  submit: ({ email, password }) => {
    if (email && password) {
      return true
    } else {
      console.warn('Neplatná data události!')
      return false
    }
  }
})

function submitForm(email, password) {
  emit('submit', { email, password })
}
</script>
js
export default {
  emits: {
    // bez validace
    click: null,

    // validace události `submit`
    submit: ({ email, password }) => {
      if (email && password) {
        return true
      } else {
        console.warn('Neplatná data události!')
        return false
      }
    }
  },
  methods: {
    submitForm(email, password) {
      this.$emit('submit', { email, password })
    }
  }
}
Události komponent (Events) has loaded