Conditions apply colours to a drawing
HTML doesn’t have a way to express logic, such as conditions and loops. Svelte does.
To conditionally render something, we wrap it in an if block:
{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>{/if} {#if ! user.loggedIn}<button on:click={toggle}>
Log in
</button>
{/if}
Copy the code
The complete code is as follows:
<script>
let user = { loggedIn: false };
function toggle() { user.loggedIn = ! user.loggedIn; }</script>
{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>{/if} {#if ! user.loggedIn}<button on:click={toggle}>
Log in
</button>
{/if}
Copy the code
Click the button, the button will switch between Log out and Log in.
Because there are two conditions: if user.loggetin and if! Loggetin, which are mutually exclusive, we can simplify this component by using an else block:
{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{:else}
<button on:click={toggle}>
Log in
</button>
{/if}
Copy the code
The # character always indicates the block start tag. The/character always represents an end-of-block flag. : characters, such as {:else}, indicate that the block continues to flag. Don’t worry, you’ve already learned almost all the new syntax Svelte adds to HTML.
The complete code is as follows:
<script>
let user = { loggedIn: false };
function toggle() { user.loggedIn = ! user.loggedIn; }</script>
{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{:else}
<button on:click={toggle}>
Log in
</button>
{/if}
Copy the code
Oh, I forgot, there are multiple conditions:
<script>
let x = 7;
</script>
{#if x > 10}
<p>{x} is greater than 10</p>
{:else if 5 > x}
<p>{x} is less than 5</p>
{:else}
<p>{x} is between 5 and 10</p>
{/if}
Copy the code
Render loop
If you need to loop through the list of data, use the each block:
<ul>
{#each cats as cat}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{cat.name}
</a></li>
{/each}
</ul>
Copy the code
The expression (in this case, CATS) can be any array or array-like object (that is, it has the length attribute). You can do this with each […iterable].
You can use the second argument as the index variable for the current traversal object, as shown below:
{#each cats as cat, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{i + 1}: {cat.name}
</a></li>
{/each}
Copy the code
If you wish, you can deconstruct each cats as {ID,name}, which replaces cat.id and cat.name with ID and name.
The complete code is as follows:
<script>
let cats = [
{ id: 'J---aiyznGQ'.name: 'Keyboard Cat' },
{ id: 'z_AbfPXTKms'.name: 'Maru' },
{ id: 'OUtn3pvWmpg'.name: 'Henri The Existential Cat'}];</script>
<h1>The Famous Cats of YouTube</h1>
<ul>
{#each cats as { id, name }, i}
<li><a target="_blank" href="https://www.youtube.com/watch?v={id}">
{i + 1}: {name}
</a></li>
{/each}
</ul>
Copy the code
The function and use of key
It’s a little hard to describe in words. Here’s an example:
Next, let’s click on the “Remove First Thing” button. Here, you should know what you want to get by deleting the first line:
Oh NO!! That’s not what I want, and I don’t think it’s what you want either. How can banana be an apple?
How to deal with it?
This is where the key comes in.
Code without key:
<button on:click={handleClick}>
Remove first thing
</button>
{#each things as thing}
<Thing name={thing.name}/>
{/each}
Copy the code
Add key:
<button on:click={handleClick}>
Remove first thing
</button>
{#each things as thing (thing.id) }
<Thing name={thing.name}/>
{/each}
Copy the code
See the difference? Here, thing.id is the key that tells Svelte how to determine which DOM node to change when the component is updated.
You can use any object as a key because Svelte uses maps internally. In other words, you can use thing instead of thing.id. However, it is often safer to use strings or numbers because it means that the identity does not reference the equation, for example, when updating with new data from the API server.
The complete code is as follows:
The file App. Sevlte
<script>
import Thing from './Thing.svelte';
let things = [
{ id: 1.name: 'apple' },
{ id: 2.name: 'banana' },
{ id: 3.name: 'carrot' },
{ id: 4.name: 'doughnut' },
{ id: 5.name: 'egg'},];function handleClick() {
things = things.slice(1);
}
</script>
<button on:click={handleClick}>
Remove first thing
</button>
{#each things as thing (thing.id) }
<Thing name={thing.name}/>
{/each}
Copy the code
File Thing. Sevlte
<script>
const emojis = {
apple: "🍎".banana: "🍌".carrot: "🥕".doughnut: "🍩".egg: "🥚"
}
// the name is updated whenever the prop value changes...
export let name;
/ /... but the "emoji" variable is fixed upon initialisation of the component
const emoji = emojis[name];
</script>
<p>
<span>The emoji for { name } is { emoji }</span>
</p>
<style>
p {
margin: 0.8 em 0;
}
span {
display: inline-block;
padding: 0.2 em 1em 0.3 em;
text-align: center;
border-radius: 0.2 em;
background-color: #FFDFD3;
}
</style>
Copy the code
Asynchronous rendering
When I look at the document, when I see this place, my eyes lit up. Now I’m going to introduce the asynchronous rendering block added to HTML in Sevlte.
Most Web applications must handle asynchronous data at some point. You can easily wait for the data to return in your tag:
{#await promise}
<p>. waiting</p>
{:then number}
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
Copy the code
Consider only the latest promise, which means you don’t need to worry about timing.
If you know your promise will not be rejected, you can omit the catch block. If you don’t want to show anything, you can also omit the first block until the promise ends:
{#await promise then value}
<p>the value is {value}</p>
{/await}
Copy the code
The complete code is as follows:
<script>
async function getRandomNumber() {
const res = await fetch(`tutorial/random-number`);
const text = await res.text();
if (res.ok) {
return text;
} else {
throw new Error(text); }}let promise = getRandomNumber();
function handleClick() {
promise = getRandomNumber();
}
</script>
<button on:click={handleClick}>
generate random number
</button>
{#await promise}
<p>. waiting</p>
{:then number}
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
Copy the code
Running result:
or
If you don’t enjoy watching it and want to try it yourself, you can go to the official website to try it online: await-blocks