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/18-advanced.md

151 lines
3.9 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

---
title: Advanced
---
### Keyed each blocks
Associating a *key* with a block allows Svelte to be smarter about how it adds and removes items to and from a list. To do so, add an `(expression)` that uniquely identifies each member of the list:
```html
<!-- { repl: false } -->
{#each people as person (person.name)}
<div>{person.name}</div>
{/each}
```
It's easier to show the effect of this than to describe it. Open the following example in the REPL:
```html
<!-- { title: 'Keyed each blocks' } -->
<button on:click="update()">update</button>
<section>
<h2>Keyed</h2>
{#each people as person (person.name)}
<div transition:slide>{person.name}</div>
{/each}
</section>
<section>
<h2>Non-keyed</h2>
{#each people as person}
<div transition:slide>{person.name}</div>
{/each}
</section>
<style>
button {
display: block;
}
section {
width: 10em;
float: left;
}
</style>
<script>
import { slide } from 'svelte-transitions';
var people = ['Alice', 'Barry', 'Cecilia', 'Douglas', 'Eleanor', 'Felix', 'Grace', 'Horatio', 'Isabelle'];
function random() {
return people
.filter(() => Math.random() < 0.5)
.map(name => ({ name }))
}
export default {
data() {
return { people: random() };
},
methods: {
update() {
this.set({ people: random() });
}
},
transitions: { slide }
};
</script>
```
### Hydration
If you're using [server-side rendering](guide#server-side-rendering), it's likely that you'll need to create a client-side version of your app *on top of* the server-rendered version. A naive way to do that would involve removing all the existing DOM and rendering the client-side app in its place:
```js
import App from './App.html';
const target = document.querySelector('#element-with-server-rendered-html');
// avoid doing this!
target.innerHTML = '';
new App({
target
});
```
Ideally, we want to reuse the existing DOM instead. This process is called *hydration*. First, we need to tell the compiler to include the code necessary for hydration to work by passing the `hydratable: true` option:
```js
const { js } = svelte.compile(source, {
hydratable: true
});
```
(Most likely, you'll be passing this option to [rollup-plugin-svelte](https://github.com/rollup/rollup-plugin-svelte) or [svelte-loader](https://github.com/sveltejs/svelte-loader).)
Then, when we instantiate the client-side component, we tell it to use the existing DOM with `hydrate: true`:
```js
import App from './App.html';
const target = document.querySelector('#element-with-server-rendered-html');
new App({
target,
hydrate: true
});
```
> It doesn't matter if the client-side app doesn't perfectly match the server-rendered HTML — Svelte will repair the DOM as it goes.
### Immutable
Because arrays and objects are *mutable*, Svelte must err on the side of caution when deciding whether or not to update things that refer to them.
But if all your data is [immutable](https://en.wikipedia.org/wiki/Immutable_object), you can use the `{ immutable: true }` compiler option to use strict object comparison (using `===`) everywhere in your app. If you have one component that uses immutable data you can set it to use the strict comparison for just that component.
In the example below, `searchResults` would normally be recalculated whenever `items` *might* have changed, but with `immutable: true` it will only update when `items` has *definitely* changed. This can improve the performance of your app.
```html
<!-- { repl: false } -->
{#each searchResults as item}
<div>{item.name}</div>
{/each}
<script>
import FuzzySearch from 'fuzzy-search';
export default {
immutable: true,
computed: {
searchResults: ({ searchString, items }) => {
if (!searchString) return items;
const searcher = new FuzzySearch(items, ['name', 'location']);
return searcher.search(searchString);
}
}
}
</script>
```
[Here's a live example](repl?demo=immutable) showing the effect of `immutable: true`.