DEV Community

Cover image for Svelte Series-3: How to Update Data and Use Event Listeners
Garlic Garlic
Garlic Garlic

Posted on

Svelte Series-3: How to Update Data and Use Event Listeners

Data Binding

Data is the most important aspect of page presentation.

In React, we can declare and store variables in this.state, or manipulate them with useState; in Vue, we can put the data in the return value of the data() method, or declare variables with ref or reactive; and in Svelte, we declare variables directly in script tags as normal. In Svelte, we declare variables in script tags and wrap them in html tags with {}.

<script>
  let count = 0;
</script>

<div>count: {count}</div>
Enter fullscreen mode Exit fullscreen mode

In addition to displaying in the tag content, we can manipulate variables in the tag attributes, for example, we often need to determine the dynamic style class.

<script>
  let tab = 'hello'
</script>

<span class={tab === 'hello' ? 'active' : ''}>color text</span>

<style>
.active {
  color: blue;
}
</style>
Enter fullscreen mode Exit fullscreen mode

Update data

How do we update declared variables? It's also very easy:

<script>
  let count = 0;

  const updateCount = () => {
    if (count >= 5) {
      return;
    }
    count++;
    setTimeout(() => {
      updateCount();
    }, 1000);
  };

  updateCount();
</script>

<span>count: {count}</span>
Enter fullscreen mode Exit fullscreen mode

In the above code, I declared a timed update method, if you execute the above code, you can see the count in the page updated by seconds. From the code we can see that there is no difference between declaring and using methods and the way we normally write vanilla js.

Update array and object

If you have used Vue, then you must know that in Vue, some Hack operations are required for array updates. What about in Svelte?

Here's an example:

<script>
  let arr = [1];

  const updateArray = () => {
    arr.push(1);
    console.log(arr);
  };
</script>

<button on:click={updateArray}>update array</button>
<p>array: {arr.join(",")}</p>
Enter fullscreen mode Exit fullscreen mode

In this example, if we click on the button, we see that the contents of the array are not updated at all on the page display, yet the console prints out the contents of the array after the push as normal.

Yes, updating arrays in Svelte also requires some finesse.

Because Svelte's reactivity is triggered by assignments, using array methods like push and splice won't automatically cause updates.

This is a quote from the official website: the reactivity of Svelte is triggered by assignment statements. This sentence already points out the key problem: "assignment statement". So we can modify it as follows:

const updateArray = () => {
  arr.push(1);
  console.log(arr);
+ arr = arr;
}
Enter fullscreen mode Exit fullscreen mode

or like this:

const updateArray = () => {
  arr = [...arr, 1]
}
Enter fullscreen mode Exit fullscreen mode

For some other methods of manipulating arrays, we can replace them along these lines

const pushNumber = () => {
  arr = [...arr, lastNumber];
}
const popNumber = () => {
  arr = [...arr.slice(0, arr.length - 1)]
}
const unshiftNumber = () => {
  arr = [firstNumber, ...arr];
}
const shiftNumber = () => {
  arr = [...arr.slice(1, arr.length)]
}
Enter fullscreen mode Exit fullscreen mode

There is also one thing to keep in mind when objects are updated, as an example:

<script>
  let obj = {
    foo: {
      bar: "hello",
    },
  };
  let bar = obj.foo.bar;
  bar = "world";
</script>

<p>object: {obj.foo.bar}</p>
Enter fullscreen mode Exit fullscreen mode

On the page, we still see hello, and to update it, we need to write it as follows:

<script>
  let obj = {
    foo: {
      bar: "hello",
    },
  };
  obj.foo.bar = "world";
  // let bar = obj.foo.bar;
  // bar = 'world'
</script>

<p>object: {obj.foo.bar}</p>
Enter fullscreen mode Exit fullscreen mode

The official website also carefully gives us a hint: the name of the updated variable must appear on the left hand side of the assignment

Event Handlers

Each framework has its own unique way of writing event listeners. In Svelte, event listeners are bound in the following format.

on:eventname|modifiers={handler}
Enter fullscreen mode Exit fullscreen mode

eventname like clickmousemovekeydown and etc。

modifiersis an optional option with some options like:

  • preventDefault: calls event.preventDefault() before running the handler. Useful for client-side form handling.
  • stopPropagation: calls event.stopPropagation(), preventing the event reaching the next element.
  • passive: improves scrolling performance on touch/wheel events
  • capture: fires the handler during the capture phase instead of the bubbling phase
  • once: remove the handler after the first time it runs

For example, let's write one of the most common event bindings that binds a data declaration to an event listener:

<script>
  let count = 0;
  const updateCount = () => {
    count++;
  };
</script>

<div>
  count: {count}
  <button on:click={updateCount}>+1</button>
</div>
Enter fullscreen mode Exit fullscreen mode

In the above code, We're not using event modifiers for now, let's see another example:

<script>
  let count = 0;
  const sayHello = () => {
    console.log("hello");
  };

  const updateCount = () => {
    count++;
  };
</script>

<div on:click={sayHello}>
  count: {count}
  <button on:click={updateCount}>+1</button>
</div>
Enter fullscreen mode Exit fullscreen mode

If we click on the button at this point, we will see the hello string being printed in the console. One way to stop the event from bubbling is to set stopPropagation in the listener method.

const updateCount = (event) => {
  event.stopPropagation();
  count++;
}
Enter fullscreen mode Exit fullscreen mode

Another way is to use the modifiers we just described so that we don't have to deal with the bubbling logic in our business code:

<button on:click|stopPropagation={updateCount}>+1</button>
Enter fullscreen mode Exit fullscreen mode

Event modifiers support chained calls:

on:eventname|modifier1|modifier2|modifier3={handler}
Enter fullscreen mode Exit fullscreen mode

Sometimes we need to get the event object in the event binding, and the way to get the event object is also divided into cases, one is the event does not accept other parameters:

<script>
  const handleClick = (event) => {
    console.log(event);
  };
</script>

<button on:click={handleClick}>btn</button>
Enter fullscreen mode Exit fullscreen mode

In the other case, we need to have the method take other parameters in addition to the event object:

<script>
  const handleClick = (event, param) => {
    console.log(event, param);
  };
</script>

<button on:click={(e) => handleClick(e, "hello")}>btn</button>
Enter fullscreen mode Exit fullscreen mode

This inline event binding can also be written as follows, with the main difference being highlighting support under certain editors:

<button on:click="{e => handleClick(e, 'hello')}">btn</button>
Enter fullscreen mode Exit fullscreen mode

Brief Summary

In this chapter we have learned:

  • Declaring data and updating data in Svelte
  • Tips for updating arrays, objects in Svelte
  • How to use event listeners in Svelte, and the use of modifiers in listening to events.

Top comments (0)