본문 바로가기
Web/JavaScript

[Svelte] Event Handling

by llHoYall 2021. 11. 30.

Let's learn how to handle the event in Svelte.

  • Event Bubbling : propagating the event from child to parent
  • Event Capturing : propagating the event from parent to child

Inline Event Handler

DOM can have an inline event handler using on:click in Svelte.

<script lang="ts">
  let text = 'Test';
</script>

<div on:click={() => (text += '.')}>
  {text}
</div>

Multiple Event Handler

You can use multiple events with a single element.

<script lang="ts">
  let count = 0;

  function increase() {
    count++;
  }

  function print() {
    console.log(`count: ${count}`);
  }

  function currentTarget(e) {
    console.log(e.currentTarget);
  }
</script>

<h1>{count}</h1>
<button on:click={increase} on:click={print} on:click={currentTarget}>Test</button>

Event Modifiers

Svelte provides several event modifiers.

preventDefault

preventDefault modifier prevents the default action of the event.

<script lang="ts">
  function currentTarget(e) {
    console.log(e.currentTarget);
  }
</script>

<h1>preventDefault</h1>
<a href="https://hdevstudy.tistory.com" target="_blank" on:click|preventDefault={currentTarget}>
  HoYa's Tistory Blog
</a>

This hyperlink will not work because of the preventDefault modifier.

stopPropagation

stopPropagation modifier stops event propagation.

In other words, it doesn't propagate an event to the upper element.

<script lang="ts">
  function currentTarget(e) {
    console.log(e.currentTarget);
  }
</script>

<h1>stopPropagation</h1>
<div on:click={currentTarget}>
  <div on:click|stopPropagation={currentTarget}>Test</div>
</div>

passive and nonpassive

passive modifier improves scrolling performance on touch/wheel events. Svelte will add this automatically where it's safe to do so.

nonpassive modifier explicitly set "passive:false".

<script lang="ts">
  function currentEvent(e) {
    console.log(e);
  }
</script>

<h1>passive</h1>
<div class="parent wheel" on:wheel|passive={currentEvent}>
  <div class="child wheel" />
</div>

<style>
  .parent {
    width: 50px;
    height: 50px;
    background-color: tomato;
  }
    
  .parent.wheel {
    overflow: auto;
  }

  .child.wheel {
    height: 1000%;
  }
</style>

capture

capture modifier captures the event of the child.

<script lang="ts">
  function currentTarget(e) {
    console.log(e.currentTarget);
  }
</script>

<h1>capture</h1>
<div on:click|capture={currentTarget}>
  <div on:click={currentTarget}>Test</div>
</div>

once

once modifier removes the event handler once executed.

<script lang="ts">
  function currentTarget(e) {
    console.log(e.currentTarget);
  }
</script>

<h1>once</h1>
<a
  href="https://hdevstudy.tistory.com"
  target="_blank"
  on:click|preventDefault|once={currentTarget}
>
  HoYa's Tistory Blog
</a>

This hyperlink will not work at first, but it work after then.

And, currentTarget() function is run once.

self

self modifier only triggers event handler if event target is itself.

<script lang="ts">
  function currentTarget(e) {
    console.log(e.currentTarget);
  }
</script>

<h1>self</h1>
<div class="parent" on:click|self={currentTarget}>
  <div class="child" />
</div>

<style>
  .parent {
    width: 50px;
    height: 50px;
    background-color: tomato;
  }

  .child {
    width: 30px;
    height: 30px;
    background-color: teal;
  }
</style>

Event Dispatcher

Svelte's component can generate events and pass the data to the parent component.

<!-- components/EventDispatcher.svelte -->
<script lang="ts">
  import { createEventDispatcher } from 'svelte';

  const dispatch = createEventDispatcher();

  function sendEvent() {
    dispatch('fromChild1');
  }

  function sendEventWithData() {
    dispatch('fromChild2', 7);
  }
</script>

<div>
  <button on:click={sendEvent}>Send Event 1</button>
  <button on:click={sendEventWithData}>Send Event 2</button>
</div>

First, create a dispatcher.

Next, dispatch your own event.

you can pass the data as well.

<script lang="ts">
  import EventDispatcher from '../components/EventDispatcher.svelte';

  function currentEvent(e) {
    console.log(e);
  }
</script>

<EventDispatcher on:fromChild1={currentEvent} on:fromChild2={currentEvent} />

You can handle the passed event by on: directive.

And, you can get the data from the detail field of the event.

Event Forwarding

The events of components aren't bubbling unlike the events of DOM elements.

Therefore, you have to send it manually.

<!-- components/EventChild.svelte -->
<script lang="ts">
  import { createEventDispatcher } from 'svelte';

  const dispatch = createEventDispatcher();
</script>

<h2>Child</h2>
<button on:click={() => dispatch('childEvent', { name: 'HoYa', age: 18 })}>
  Child
</button>

For example, I created a custom event with object literal.

<!-- components/EventParent.svelte -->
<script lang="ts">
  import EventChild from './EventChild.svelte';
</script>

<h1>Parent</h1>
<EventChild on:childEvent />

Just specify the event via on: directive from the child component.

<script lang="ts">
  import EventParent from '../components/EventParent.svelte';

  function currentEvent(e) {
    console.log(e);
  }
</script>

<EventParent on:childEvent={currentEvent} />

Then, it can be passed to the upper component.

The object in the event is also included.

'Web > JavaScript' 카테고리의 다른 글

[Svelte] Context  (0) 2021.12.04
[Svelte] Action  (0) 2021.12.02
[Svelte] Slot  (0) 2021.11.28
[Svelte] Props  (0) 2021.11.27
[Svelte] Reactivity  (0) 2021.11.25

댓글