6.3 KiB
title |
---|
Template syntax |
Rather than reinventing the wheel, Svelte templates are built on foundations that have stood the test of time: HTML, CSS and JavaScript. There's very little extra stuff to learn.
Tags
Tags allow you to bind data to your template. Whenever your data changes (for example after component.a = 3
), the DOM updates automatically. You can use any JavaScript expression in templates, and it will also automatically update:
<!-- { title: 'Template tags' } -->
<p>{a} + {b} = {a + b}</p>
/* { hidden: true } */
{
"a": 1,
"b": 2
}
You can also use tags in attributes:
<!-- { title: 'Tags in attributes' } -->
<h1 style="color: {color};">{color}</h1>
<p hidden={hideParagraph}>You can hide this paragraph.</p>
/* { hidden: true } */
{
color: "steelblue",
hideParagraph: false
}
Boolean attributes like hidden
will be omitted if the tag expression evaluates to false. Attributes will be removed from the element if their value is undefined
or null
.
HTML
Ordinary tags render expressions as plain text. If you need your expression interpreted as HTML, wrap it in a special @html
tag:
<!-- { title: 'Triple tags' } -->
<p>This HTML: {content}</p>
<p>Renders as: {@html content}</p>
/* { hidden: true } */
{
content: "Some <b>bold</b> text."
}
As with regular tags, you can use any JavaScript expression in HTML tags, and it will automatically update the document when your data changes.
HTML is not sanitized before it is rendered! If you are displaying user input, you are responsible for first sanitizing it. Not doing so potentially opens you up to XSS attacks.
If blocks
Control whether or not part of your template is rendered by wrapping it in an if block.
<!-- { repl: false } -->
{#if user.loggedIn}
<a href="/logout">log out</a>
{/if}
{#if !user.loggedIn}
<a href="/login">log in</a>
{/if}
You can combine the two blocks above with {:else}
:
<!-- { repl: false } -->
{#if user.loggedIn}
<a href="/logout">log out</a>
{:else}
<a href="/login">log in</a>
{/if}
You can also use {:else if ...}
:
<!--{ title: 'If, else and else if' }-->
{#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}
/* { hidden: true } */
{
x: 7
}
Each blocks
Iterate over lists of data:
<!--{ title: 'Each blocks' }-->
<h1>Cats of YouTube</h1>
<ul>
{#each cats as cat}
<li><a target="_blank" href={cat.video}>{cat.name}</a></li>
{:else}
<li>No cats :(</li>
{/each}
</ul>
/* { hidden: true } */
{
cats: [
{
name: "Keyboard Cat",
video: "https://www.youtube.com/watch?v=J---aiyznGQ"
},
{
name: "Maru",
video: "https://www.youtube.com/watch?v=z_AbfPXTKms"
},
{
name: "Henri The Existential Cat",
video: "https://www.youtube.com/watch?v=OUtn3pvWmpg"
}
]
}
Else is triggered when the list is empty.
You can access the index of the current element with expression as name, index:
<!--{ title: 'Each block indexes' }-->
<div class="grid">
{#each rows as row, y}
<div class="row">
{#each columns as column, x}
<code class="cell">
{x + 1},{y + 1}:
<strong>{row[column]}</strong>
</code>
{/each}
</div>
{/each}
</div>
/* { hidden: true } */
{
columns: ["foo", "bar", "baz"],
rows: [
{ foo: "a", bar: "b", baz: "c" },
{ foo: "d", bar: "e", baz: "f" },
{ foo: "g", bar: "h", baz: "i" }
]
}
By default, if the list
a, b, c
becomesa, c
, Svelte will remove the third block and change the second fromb
toc
, rather than removingb
. If that's not what you want, use a keyed each block.
You can use destructuring patterns on the elements of the array:
<!--{ title: 'Each block destructuring' }-->
<h1>It's the cats of YouTube again</h1>
<ul>
{#each cats as {name, video} }
<li><a target="_blank" href={video}>{name}</a></li>
{/each}
</ul>
/* { hidden: true } */
{
cats: [
{
name: "Keyboard Cat",
video: "https://www.youtube.com/watch?v=J---aiyznGQ"
},
{
name: "Maru",
video: "https://www.youtube.com/watch?v=z_AbfPXTKms"
},
{
name: "Henri The Existential Cat",
video: "https://www.youtube.com/watch?v=OUtn3pvWmpg"
}
]
}
Await blocks
You can represent the three states of a Promise — pending, fulfilled and rejected — with an await
block:
<!--{ title: 'Await blocks' }-->
<script>
const promise = new Promise(fulfil => {
setTimeout(() => fulfil(42), 3000);
});
</script>
{#await promise}
<p>wait for it...</p>
{:then answer}
<p>the answer is {answer}!</p>
{:catch error}
<p>well that's odd</p>
{/await}
If the expression in {#await expression}
isn't a promise, Svelte skips ahead to the then
section.
Directives
Directives allow you to add special instructions for adding event handlers, bindings, transitions and so on. We'll cover each of those in later stages of this guide – for now, all you need to know is that directives can be identified by the :
character:
<!--{ title: 'Element directives' }-->
<p>Count: {count}</p>
<button on:click="{() => count += 1}">+1</button>
/* { hidden: true } */
{
count: 0
}
Technically, the
:
character is used to denote namespaced attributes in HTML. These will not be treated as directives, if encountered.
Debug tags
To inspect data as it changes and flows through your app, use a {@debug ...}
tag:
<!--{ title: 'Debug tags' }-->
<input bind:value={name}>
{@debug name}
<h1>Hello {name}!</h1>
/* { hidden: true } */
{
name: 'world'
}
This will log the value of name
whenever it changes. If your devtools are open, changing name
will pause execution and open the debugger.
You can debug multiple values simultaneously ({@debug foo, bar, baz}
), or use {@debug}
to pause execution whenever the surrounding markup is updated.
Debug tags only have an effect when compiling with the
dev: true
compiler option.