diff --git a/site/content/tutorial/06-bindings/11-this/app-a/App.svelte b/site/content/tutorial/06-bindings/11-bind-this/app-a/App.svelte similarity index 100% rename from site/content/tutorial/06-bindings/11-this/app-a/App.svelte rename to site/content/tutorial/06-bindings/11-bind-this/app-a/App.svelte diff --git a/site/content/tutorial/06-bindings/11-this/app-b/App.svelte b/site/content/tutorial/06-bindings/11-bind-this/app-b/App.svelte similarity index 100% rename from site/content/tutorial/06-bindings/11-this/app-b/App.svelte rename to site/content/tutorial/06-bindings/11-bind-this/app-b/App.svelte diff --git a/site/content/tutorial/06-bindings/11-this/text.md b/site/content/tutorial/06-bindings/11-bind-this/text.md similarity index 100% rename from site/content/tutorial/06-bindings/11-this/text.md rename to site/content/tutorial/06-bindings/11-bind-this/text.md diff --git a/site/content/tutorial/09-lifecycle/01-onmount/app-a/App.svelte b/site/content/tutorial/09-lifecycle/01-onmount/app-a/App.svelte new file mode 100644 index 0000000000..e8306d1957 --- /dev/null +++ b/site/content/tutorial/09-lifecycle/01-onmount/app-a/App.svelte @@ -0,0 +1,31 @@ + + + + +

Photo album

+ +
+ {#each photos as photo} +
+ {photo.title} +
{photo.title}
+
+ {:else} + +

loading...

+ {/each} +
\ No newline at end of file diff --git a/site/content/tutorial/09-lifecycle/01-onmount/app-b/App.svelte b/site/content/tutorial/09-lifecycle/01-onmount/app-b/App.svelte new file mode 100644 index 0000000000..1b83727627 --- /dev/null +++ b/site/content/tutorial/09-lifecycle/01-onmount/app-b/App.svelte @@ -0,0 +1,38 @@ + + + + +

Photo album

+ +
+ {#each photos as photo} +
+ {photo.title} +
{photo.title}
+
+ {:else} + +

loading...

+ {/each} +
\ No newline at end of file diff --git a/site/content/tutorial/09-lifecycle/01-onmount/text.md b/site/content/tutorial/09-lifecycle/01-onmount/text.md new file mode 100644 index 0000000000..54b385e889 --- /dev/null +++ b/site/content/tutorial/09-lifecycle/01-onmount/text.md @@ -0,0 +1,28 @@ +--- +title: onMount +--- + +Every component has a *lifecycle* that starts when it is created, and ends when it is destroyed. There are a handful of functions that allow you to run code at key moments during that lifecycle. + +The one you'll use most frequently is `onMount`, which runs after the component is first rendered to the DOM. We briefly encountered it [earlier](tutorial/bind-this) when we needed to interact with a `` element after it had been rendered. + +We'll add an `onMount` handler that loads some data over the network: + +```html + +``` + +> It's recommended to put the `fetch` in `onMount` rather than at the top level of the ` + +

+ The page has been open for + {seconds} {seconds === 1 ? 'second' : 'seconds'} +

\ No newline at end of file diff --git a/site/content/tutorial/09-lifecycle/02-ondestroy/app-a/utils.js b/site/content/tutorial/09-lifecycle/02-ondestroy/app-a/utils.js new file mode 100644 index 0000000000..7b65e75c8c --- /dev/null +++ b/site/content/tutorial/09-lifecycle/02-ondestroy/app-a/utils.js @@ -0,0 +1,5 @@ +import { onDestroy } from 'svelte'; + +export function onInterval(callback, milliseconds) { + // implementation goes here +} \ No newline at end of file diff --git a/site/content/tutorial/09-lifecycle/02-ondestroy/app-b/App.svelte b/site/content/tutorial/09-lifecycle/02-ondestroy/app-b/App.svelte new file mode 100644 index 0000000000..93a721ef44 --- /dev/null +++ b/site/content/tutorial/09-lifecycle/02-ondestroy/app-b/App.svelte @@ -0,0 +1,11 @@ + + +

+ The page has been open for + {seconds} {seconds === 1 ? 'second' : 'seconds'} +

\ No newline at end of file diff --git a/site/content/tutorial/09-lifecycle/02-ondestroy/app-b/utils.js b/site/content/tutorial/09-lifecycle/02-ondestroy/app-b/utils.js new file mode 100644 index 0000000000..0f75f29e2a --- /dev/null +++ b/site/content/tutorial/09-lifecycle/02-ondestroy/app-b/utils.js @@ -0,0 +1,9 @@ +import { onDestroy } from 'svelte'; + +export function onInterval(callback, milliseconds) { + const interval = setInterval(callback, milliseconds); + + onDestroy(() => { + clearInterval(interval); + }); +} \ No newline at end of file diff --git a/site/content/tutorial/09-lifecycle/02-ondestroy/text.md b/site/content/tutorial/09-lifecycle/02-ondestroy/text.md new file mode 100644 index 0000000000..647fbaa160 --- /dev/null +++ b/site/content/tutorial/09-lifecycle/02-ondestroy/text.md @@ -0,0 +1,43 @@ +--- +title: onDestroy +--- + +To run code when your component is destroyed, use `onDestroy`. + +For example, we can add a `setInterval` function when our component initialises, and clean it up when it's no longer relevant. Doing so prevents memory leaks. + +```html + +``` + +While it's important to call lifecycle functions during the component's initialisation, it doesn't matter *where* you call them from. So if we wanted, we could abstract the interval logic into a helper function in `utils.js`... + +```js +import { onDestroy } from 'svelte'; + +export function onInterval(callback, milliseconds) { + const interval = setInterval(callback, milliseconds); + + onDestroy(() => { + clearInterval(interval); + }); +} +``` + +...and import it into our component: + +```html + +``` \ No newline at end of file diff --git a/site/content/tutorial/09-lifecycle/03-update/app-a/App.svelte b/site/content/tutorial/09-lifecycle/03-update/app-a/App.svelte new file mode 100644 index 0000000000..2081b6ab8c --- /dev/null +++ b/site/content/tutorial/09-lifecycle/03-update/app-a/App.svelte @@ -0,0 +1,106 @@ + + + + +
+

Eliza

+ +
+ {#each comments as comment} +
+ {comment.text} +
+ {/each} +
+ + +
\ No newline at end of file diff --git a/site/content/tutorial/09-lifecycle/03-update/app-b/App.svelte b/site/content/tutorial/09-lifecycle/03-update/app-b/App.svelte new file mode 100644 index 0000000000..373b6dcb6a --- /dev/null +++ b/site/content/tutorial/09-lifecycle/03-update/app-b/App.svelte @@ -0,0 +1,106 @@ + + + + +
+

Eliza

+ +
+ {#each comments as comment} +
+ {comment.text} +
+ {/each} +
+ + +
\ No newline at end of file diff --git a/site/content/tutorial/09-lifecycle/03-update/text.md b/site/content/tutorial/09-lifecycle/03-update/text.md new file mode 100644 index 0000000000..40e071630a --- /dev/null +++ b/site/content/tutorial/09-lifecycle/03-update/text.md @@ -0,0 +1,24 @@ +--- +title: beforeUpdate and afterUpdate +--- + +The `beforeUpdate` function schedules work to happen immediately before the DOM has been updated. `afterUpdate` is its counterpart, used for running code once the DOM is in sync with your data. + +Together, they're useful for doing things imperatively that are difficult to achieve in a purely state-driven way, like updating the scroll position of an element. + +This [Eliza](https://en.wikipedia.org/wiki/ELIZA) chatbot is annoying to use, because you have to keep scrolling the chat window. Let's fix that. + +```js +let div; +let autoscroll; + +beforeUpdate(() => { + autoscroll = div && (div.offsetHeight + div.scrollTop) > (div.scrollHeight - 20); +}); + +afterUpdate(() => { + if (autoscroll) div.scrollTo(0, div.scrollHeight); +}); +``` + +Note that `beforeUpdate` will first run before the component has mounted, so we need to check for the existence of `div` before reading its properties. \ No newline at end of file diff --git a/site/content/tutorial/09-lifecycle/meta.json b/site/content/tutorial/09-lifecycle/meta.json new file mode 100644 index 0000000000..2f833e2a4a --- /dev/null +++ b/site/content/tutorial/09-lifecycle/meta.json @@ -0,0 +1,3 @@ +{ + "title": "Lifecycle" +} \ No newline at end of file diff --git a/site/content/tutorial/99-todo/99-todo/text.md b/site/content/tutorial/99-todo/99-todo/text.md index 743f5ab75f..085bfd5afc 100644 --- a/site/content/tutorial/99-todo/99-todo/text.md +++ b/site/content/tutorial/99-todo/99-todo/text.md @@ -95,11 +95,10 @@ Maybe lifecycle should go first, since we're using `onMount` in the `this` demo? ## Lifecycle -* [ ] `onMount` -* [ ] `onDestroy` -* [ ] `beforeUpdate` -* [ ] `afterUpdate` -* [ ] `tick` +* [x] `onMount` +* [x] `onDestroy` +* [x] `beforeUpdate` +* [x] `afterUpdate` * [ ] how lifecycle functions behave in SSR mode? @@ -154,6 +153,7 @@ Maybe lifecycle should go first, since we're using `onMount` in the `this` demo? * [ ] Keyed each blocks * [ ] Debug tags * [ ] `context="module"` +* [ ] `tick` ---