Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
Svelte is an up and coming front end framework for developing front end web apps.
It’s simple to use and lets us create results fast.
In this article, we’ll look at how to share variables between component instances with module context.
Module Context
Svelte components can contain code that is shared between multiple component instances.
To do this, we can declare the script block with context='module'
. The code inside it will run once, when the module first evaluates, rather than when a component is instantiated.
For instance, we can use it to create multiple audio elements that can only have one audio element play at a time by stopping the ones that aren’t being played as follows:
App.svelte
:
<script>
import AudioPlayer from "./AudioPlayer.svelte";
</script>
<AudioPlayer
src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3"
/>
<AudioPlayer
src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_1MG.mp3"
/>
<AudioPlayer
src="http://www.hochmuth.com/mp3/Haydn_Cello_Concerto_D-1.mp3"
/>
AudioPlayer.svelts
:
<script context="module">
let current;
</script>
<script>
export let src;
let audio;
let paused = true;
const stopOthers = () =>{
if (current && current !== audio) current.pause();
current = audio;
}
</script>
<article>
<audio
bind:this={audio}
bind:paused
on:play={stopOthers}
controls
{src}
></audio>
</article>
In the code above, we have the AudioPlayer
component which has the code that’s shared between all instances in:
<script context="module">
let current;
</script>
This lets us call pause
on any instance of the audio element that isn’t the one that’s being played as we did in the stopOthers
function. stopOthers
is run when we click play on an audio element.
Then we included the AudioPlayer
instances in the App.svelte
component.
Therefore, when we click play on one of the audio elements, we pause the other ones.
Exports
Anything that’s exported from a context='module'
script block becomes an export of the module itself. For instance, we can create a button to stop all the audio elements in AudioPlayer
that is currently playing as follows:
App.svelte
:
<script>
import AudioPlayer, { stopAll } from "./AudioPlayer.svelte";
</script>
<button on:click={stopAll}>Stop All</button>
<AudioPlayer
src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3"
/>
<AudioPlayer
src="https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_1MG.mp3"
/>
<AudioPlayer
src="http://www.hochmuth.com/mp3/Haydn_Cello_Concerto_D-1.mp3"
/>
AudioPlayer.svelte
:
<script context="module">
let elements = new Set();
export const stopAll = () => {
elements.forEach(element => {
element.pause();
});
};
</script>
<script>
import { onMount } from 'svelte';
export let src;
let audio;
onMount(() => {
elements.add(audio);
return () => elements.delete(audio);
});
</script>
<article>
<audio
bind:this={audio}
controls
{src}
></audio>
</article>
In the code above, we add all the audio element instances to the elements
set which we created in the contex='module'
block as each AudioPlayer
component is mounted.
Then we export the stopAll
function, which has all the audio element instances from elements
, and we call pause
on all of them by looping through them and calling pause
.
In App.svelte
, we import the stopAll
function from AudioPlayer
and then call it when we click the Stop All button.
Then when we click play on one or more audio elements, they’ll all be paused when we click the Stop All button.
Note that we can’t have a default export because the component is the default export.
Conclusion
We can use the module context script block to add script blocks that are shared between all instances of a component.
If we export functions inside module context script blocks, we can import the function and then call it.