上一讲是svelte的特殊元素,这些特殊元素区别于咱们的html元素,有特殊的能力,今天咱们来看模块上下文,前面咱们也讲过上下文。我们来看看异同。
共享代码 在到目前为止我们看到的所有示例中,<script>
块包含在每个组件实例初始化时运行的代码。 对于绝大多数组件,这就是您所需要的。
有时,你需要在单个组件中的实例之外运行一些代码。例如,你可以同时播放这五个音频播放器。假设现在的交互是这么设计的:其中一个播放完毕,则同时也停止其他播放器。
来看例子:
App.svelte
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <script > import AudioPlayer from './AudioPlayer.svelte' ; </script > <AudioPlayer src="https://sveltejs.github.io/assets/music/strauss.mp3" title="The Blue Danube Waltz" composer="Johann Strauss" performer="European Archive" /> <AudioPlayer src="https://sveltejs.github.io/assets/music/holst.mp3" title="Mars, the Bringer of War" composer="Gustav Holst" performer="USAF Heritage of America Band" /> <AudioPlayer src="https://sveltejs.github.io/assets/music/satie.mp3" title="Gymnopédie no. 1" composer="Erik Satie" performer="Prodigal Procrastinator" /> <AudioPlayer src="https://sveltejs.github.io/assets/music/beethoven.mp3" title="Symphony no. 5 in Cm, Op. 67 - I. Allegro con brio" composer="Ludwig van Beethoven" performer="European Archive" /> <AudioPlayer src="https://sveltejs.github.io/assets/music/mozart.mp3" title="Requiem in D minor, K. 626 - III. Sequence - Lacrymosa" composer="Wolfgang Amadeus Mozart" performer="Markus Staab" />
AudioPlayer.svelte
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <script > export let src; export let title; export let composer; export let performer; let audio; let paused = true ; function stopOthers ( ) { }</script > <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 > <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 >
如果要实现上述的情况,我们可以通过声明一个 <script context="module">
块来做到这一点。 包含在其中的代码将在模块第一次评估时运行一次,而不是在实例化组件时运行。 将它放在 AudioPlayer.svelte
的顶部:
1 2 3 <script context ="module" > let current; </script >
现在组件可以在没有任何状态管理的情况下相互“对话”:
1 2 3 4 function stopOthers ( ) { if (current && current !== audio) current.pause(); current = audio; }
可以实际操作下来体会:
二、导出 从context="module"
代码块中导出的任意内容,都将成为模块本身的导出。如果我们从AudioPlayer.svelte
中导出stopAll
函数…
AudioPlayer.svelte
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 <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 > <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 > <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 >
然后我们可以在 App.svelte
中导入AudioPlayer.svelte
…
1 2 3 <script > import AudioPlayer, { stopAll } from './AudioPlayer.svelte' ; </script >
并在事件处理程序中使用它:
1 2 3 <button on:click ={stopAll} > stop all audio</button >
您不能有默认导出,因为该组件是默认导出。
可以实际操作下来体会:
总结
一个<script>
标签具有一个context="module"
属性,在模块首次 evaluates 时运行一次,而不是针对每个组件实例运行一次。
带有 module
声明的 <script>
内代码不具有反应性。虽然变量自身会更新,但重新分配它们不会触发重新渲染,对于多个组件之间共享的值,请考虑使用 stores
。
你不能使用 export default
来绑定,因为组件本身就是默认导出(export default)
。