chapter for context=module

pull/2132/head
Richard Harris 7 years ago
parent 2c918894df
commit e4f7a592ca

@ -0,0 +1,43 @@
<script>
import AudioPlayer from './AudioPlayer.svelte';
</script>
<!-- https://musopen.org/music/9862-the-blue-danube-op-314/ -->
<AudioPlayer
src="tutorial/music/strauss.mp3"
title="The Blue Danube Waltz"
composer="Johann Strauss"
performer="European Archive"
/>
<!-- https://musopen.org/music/43775-the-planets-op-32/ -->
<AudioPlayer
src="tutorial/music/holst.mp3"
title="Mars, the Bringer of War"
composer="Gustav Holst"
performer="USAF Heritage of America Band"
/>
<!-- https://musopen.org/music/8010-3-gymnopedies/ -->
<AudioPlayer
src="tutorial/music/satie.mp3"
title="Gymnopédie no. 1"
composer="Erik Satie"
performer="Prodigal Procrastinator"
/>
<!-- https://musopen.org/music/2567-symphony-no-5-in-c-minor-op-67/ -->
<AudioPlayer
src="tutorial/music/beethoven.mp3"
title="Symphony no. 5 in Cm, Op. 67 - I. Allegro con brio"
composer="Ludwig van Beethoven"
performer="European Archive"
/>
<!-- https://musopen.org/music/43683-requiem-in-d-minor-k-626/ -->
<AudioPlayer
src="tutorial/music/mozart.mp3"
title="Requiem in D minor, K. 626 - III. Sequence - Lacrymosa"
composer="Wolfgang Amadeus Mozart"
performer="Markus Staab"
/>

@ -0,0 +1,39 @@
<script>
import { onMount } from 'svelte';
export let src;
export let title;
export let composer;
export let performer;
let audio;
let paused = true;
onMount(() => {
// TODO: register the audio element
});
function stopOthers() {
// TODO: implement stopOthers
}
</script>
<style>
article { margin: 0 0 1em 0; max-width: 800px }
h2, p { margin: 0 0 0.3em 0; }
audio { width: 100%; margin: 0.5em 0 1em 0; }
.playing { color: #ff3e00; }
</style>
<article class:playing={!paused}>
<h2>{title}</h2>
<p><strong>{composer}</strong> / performed by {performer}</p>
<audio
bind:this={audio}
bind:paused
on:play={stopOthers}
controls
{src}
></audio>
</article>

@ -0,0 +1,43 @@
<script>
import AudioPlayer from './AudioPlayer.svelte';
</script>
<!-- https://musopen.org/music/9862-the-blue-danube-op-314/ -->
<AudioPlayer
src="tutorial/music/strauss.mp3"
title="The Blue Danube Waltz"
composer="Johann Strauss"
performer="European Archive"
/>
<!-- https://musopen.org/music/43775-the-planets-op-32/ -->
<AudioPlayer
src="tutorial/music/holst.mp3"
title="Mars, the Bringer of War"
composer="Gustav Holst"
performer="USAF Heritage of America Band"
/>
<!-- https://musopen.org/music/8010-3-gymnopedies/ -->
<AudioPlayer
src="tutorial/music/satie.mp3"
title="Gymnopédie no. 1"
composer="Erik Satie"
performer="Prodigal Procrastinator"
/>
<!-- https://musopen.org/music/2567-symphony-no-5-in-c-minor-op-67/ -->
<AudioPlayer
src="tutorial/music/beethoven.mp3"
title="Symphony no. 5 in Cm, Op. 67 - I. Allegro con brio"
composer="Ludwig van Beethoven"
performer="European Archive"
/>
<!-- https://musopen.org/music/43683-requiem-in-d-minor-k-626/ -->
<AudioPlayer
src="tutorial/music/mozart.mp3"
title="Requiem in D minor, K. 626 - III. Sequence - Lacrymosa"
composer="Wolfgang Amadeus Mozart"
performer="Markus Staab"
/>

@ -0,0 +1,46 @@
<script context="module">
const elements = new Set();
</script>
<script>
import { onMount } from 'svelte';
export let src;
export let title;
export let composer;
export let performer;
let audio;
let paused = true;
onMount(() => {
elements.add(audio);
return () => elements.delete(audio);
});
function stopOthers() {
elements.forEach(element => {
if (element !== audio) element.pause();
});
}
</script>
<style>
article { margin: 0 0 1em 0; max-width: 800px }
h2, p { margin: 0 0 0.3em 0; }
audio { width: 100%; margin: 0.5em 0 1em 0; }
.playing { color: #ff3e00; }
</style>
<article class:playing={!paused}>
<h2>{title}</h2>
<p><strong>{composer}</strong> / performed by {performer}</p>
<audio
bind:this={audio}
bind:paused
on:play={stopOthers}
controls
{src}
></audio>
</article>

@ -0,0 +1,30 @@
---
title: Sharing code
---
In all the examples we've seen so far, the `<script>` block contains code that runs when each component instance is initialised. For the vast majority of components, that's all you'll ever need.
Very occasionally, you'll need to run some code outside of an individual component instance. For example, you can play all five of these audio players simultaneously; it would be better if playing one stopped all the others.
We can do that by declaring a `<script context="module">` block. Code contained inside it will run once, when the module first evaluates, rather than when a component is instantiated. Place this at the top of `AudioPlayer.svelte`:
```html
<script context="module">
const elements = new Set();
</script>
```
It's now possible for the components to 'talk' to each other without any state management:
```js
onMount(() => {
elements.add(audio);
return () => elements.delete(audio);
});
function stopOthers() {
elements.forEach(element => {
if (element !== audio) element.pause();
});
}
```

@ -0,0 +1,47 @@
<script>
import AudioPlayer from './AudioPlayer.svelte';
</script>
<button>
stop all audio
</button>
<!-- https://musopen.org/music/9862-the-blue-danube-op-314/ -->
<AudioPlayer
src="tutorial/music/strauss.mp3"
title="The Blue Danube Waltz"
composer="Johann Strauss"
performer="European Archive"
/>
<!-- https://musopen.org/music/43775-the-planets-op-32/ -->
<AudioPlayer
src="tutorial/music/holst.mp3"
title="Mars, the Bringer of War"
composer="Gustav Holst"
performer="USAF Heritage of America Band"
/>
<!-- https://musopen.org/music/8010-3-gymnopedies/ -->
<AudioPlayer
src="tutorial/music/satie.mp3"
title="Gymnopédie no. 1"
composer="Erik Satie"
performer="Prodigal Procrastinator"
/>
<!-- https://musopen.org/music/2567-symphony-no-5-in-c-minor-op-67/ -->
<AudioPlayer
src="tutorial/music/beethoven.mp3"
title="Symphony no. 5 in Cm, Op. 67 - I. Allegro con brio"
composer="Ludwig van Beethoven"
performer="European Archive"
/>
<!-- https://musopen.org/music/43683-requiem-in-d-minor-k-626/ -->
<AudioPlayer
src="tutorial/music/mozart.mp3"
title="Requiem in D minor, K. 626 - III. Sequence - Lacrymosa"
composer="Wolfgang Amadeus Mozart"
performer="Markus Staab"
/>

@ -0,0 +1,46 @@
<script context="module">
const elements = new Set();
</script>
<script>
import { onMount } from 'svelte';
export let src;
export let title;
export let composer;
export let performer;
let audio;
let paused = true;
onMount(() => {
elements.add(audio);
return () => elements.delete(audio);
});
function stopOthers() {
elements.forEach(element => {
if (element !== audio) element.pause();
});
}
</script>
<style>
article { margin: 0 0 1em 0; max-width: 800px }
h2, p { margin: 0 0 0.3em 0; }
audio { width: 100%; margin: 0.5em 0 1em 0; }
.playing { color: #ff3e00; }
</style>
<article class:playing={!paused}>
<h2>{title}</h2>
<p><strong>{composer}</strong> / performed by {performer}</p>
<audio
bind:this={audio}
bind:paused
on:play={stopOthers}
controls
{src}
></audio>
</article>

@ -0,0 +1,47 @@
<script>
import AudioPlayer, { stopAll } from './AudioPlayer.svelte';
</script>
<button on:click={stopAll}>
stop all audio
</button>
<!-- https://musopen.org/music/9862-the-blue-danube-op-314/ -->
<AudioPlayer
src="tutorial/music/strauss.mp3"
title="The Blue Danube Waltz"
composer="Johann Strauss"
performer="European Archive"
/>
<!-- https://musopen.org/music/43775-the-planets-op-32/ -->
<AudioPlayer
src="tutorial/music/holst.mp3"
title="Mars, the Bringer of War"
composer="Gustav Holst"
performer="USAF Heritage of America Band"
/>
<!-- https://musopen.org/music/8010-3-gymnopedies/ -->
<AudioPlayer
src="tutorial/music/satie.mp3"
title="Gymnopédie no. 1"
composer="Erik Satie"
performer="Prodigal Procrastinator"
/>
<!-- https://musopen.org/music/2567-symphony-no-5-in-c-minor-op-67/ -->
<AudioPlayer
src="tutorial/music/beethoven.mp3"
title="Symphony no. 5 in Cm, Op. 67 - I. Allegro con brio"
composer="Ludwig van Beethoven"
performer="European Archive"
/>
<!-- https://musopen.org/music/43683-requiem-in-d-minor-k-626/ -->
<AudioPlayer
src="tutorial/music/mozart.mp3"
title="Requiem in D minor, K. 626 - III. Sequence - Lacrymosa"
composer="Wolfgang Amadeus Mozart"
performer="Markus Staab"
/>

@ -0,0 +1,52 @@
<script context="module">
const elements = new Set();
export function stopAll() {
elements.forEach(element => {
element.pause();
});
}
</script>
<script>
import { onMount } from 'svelte';
export let src;
export let title;
export let composer;
export let performer;
let audio;
let paused = true;
onMount(() => {
elements.add(audio);
return () => elements.delete(audio);
});
function stopOthers() {
elements.forEach(element => {
if (element !== audio) element.pause();
});
}
</script>
<style>
article { margin: 0 0 1em 0; max-width: 800px }
h2, p { margin: 0 0 0.3em 0; }
audio { width: 100%; margin: 0.5em 0 1em 0; }
.playing { color: #ff3e00; }
</style>
<article class:playing={!paused}>
<h2>{title}</h2>
<p><strong>{composer}</strong> / performed by {performer}</p>
<audio
bind:this={audio}
bind:paused
on:play={stopOthers}
controls
{src}
></audio>
</article>

@ -0,0 +1,35 @@
---
title: Exports
---
Anything exported from a `context="module"` script block becomes an export from the module itself. If we export a `stopAll` function from `AudioPlayer.svelte`...
```html
<script context="module">
const elements = new Set();
export function stopAll() {
elements.forEach(element => {
element.pause();
});
}
</script>
```
...we can then import it from `App.svelte`...
```html
<script>
import AudioPlayer, { stopAll } from './AudioPlayer.svelte';
</script>
```
...and use it in an event handler:
```html
<button on:click={stopAll}>
stop all audio
</button>
```
> You can't have a default export, because the component *is* the default export.

@ -0,0 +1,3 @@
{
"title": "Module context"
}

@ -68,8 +68,8 @@ Another one should cover how to set up an editor for syntax highlighting.
* [x] deep/contextual bindings * [x] deep/contextual bindings
* [x] Dimensions * [x] Dimensions
* [x] `this` * [x] `this`
* [ ] shorthand * [x] shorthand
* [ ] component bindings * [x] component bindings
Maybe lifecycle should go first, since we're using `onMount` in the `this` demo? Maybe lifecycle should go first, since we're using `onMount` in the `this` demo?
@ -98,7 +98,7 @@ Maybe lifecycle should go first, since we're using `onMount` in the `this` demo?
* [x] `onDestroy` * [x] `onDestroy`
* [x] `beforeUpdate` * [x] `beforeUpdate`
* [x] `afterUpdate` * [x] `afterUpdate`
* [ ] how lifecycle functions behave in SSR mode? * [x] how lifecycle functions behave in SSR mode?
## Transitions ## Transitions
@ -147,18 +147,17 @@ Maybe lifecycle should go first, since we're using `onMount` in the `this` demo?
* [x] `<svelte:window>` * [x] `<svelte:window>`
* [x] `<svelte:body>` * [x] `<svelte:body>`
* [x] `<svelte:head>` * [x] `<svelte:head>`
* [ ] `<svelte:options>`
## Miscellaneous ## Module context
* [ ] Debug tags * [x] sharing code
* [ ] `context="module"` * [x] exports
* [ ] `tick`
--- ## Miscellaneous
## Bugs etc * [ ] Debug tags
* [ ] `tick`
* 'Show me' should be greyed out if current state is identical to target state
* Clicking 'Show me' shouldn't change the file you're looking at
Loading…
Cancel
Save