You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/site/content/guide/02-template-syntax.md

282 lines
6.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
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:
```html
<!-- { title: 'Template tags' } -->
<p>{a} + {b} = {a + b}</p>
```
```json
/* { hidden: true } */
{
"a": 1,
"b": 2
}
```
You can also use tags in attributes:
```html
<!-- { title: 'Tags in attributes' } -->
<h1 style="color: {color};">{color}</h1>
<p hidden={hideParagraph}>You can hide this paragraph.</p>
```
```json
/* { hidden: true } */
{
color: "steelblue",
hideParagraph: false
}
```
[Boolean attributes](https://www.w3.org/TR/html5/infrastructure.html#sec-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:
```html
<!-- { title: 'Triple tags' } -->
<p>This HTML: {content}</p>
<p>Renders as: {@html content}</p>
```
```json
/* { 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.
```html
<!-- { 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}`:
```html
<!-- { 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 ...}`:
```html
<!--{ 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}
```
```json
/* { hidden: true } */
{
x: 7
}
```
### Each blocks
Iterate over lists of data:
```html
<!--{ 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>
```
```json
/* { 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*:
```html
<!--{ 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>
```
```json
/* { 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` becomes `a, c`, Svelte will *remove* the third block and *change* the second from `b` to `c`, rather than removing `b`. If that's not what you want, use a [keyed each block](docs#keyed-each-blocks).
You can use destructuring patterns on the elements of the array:
```html
<!--{ 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>
```
```json
/* { 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — pending, fulfilled and rejected — with an `await` block:
```html
<!--{ 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](docs#event-handlers), [bindings](docs#bindings), [transitions](docs#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:
```html
<!--{ title: 'Element directives' }-->
<p>Count: {count}</p>
<button on:click="{() => count += 1}">+1</button>
```
```json
/* { 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:
```html
<!--{ title: 'Debug tags' }-->
<input bind:value={name}>
{@debug name}
<h1>Hello {name}!</h1>
```
```json
/* { 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.