传递对象作为道具在苗条使对象字段不改变在HTML?



我有这个苗条的代码:

Player.svelte:

<script>
import PlayerControls from './PlayerControls.svelte';
let audio;
</script>
<audio src={...} bind:this={audio} />
<PlayerControls {audio} />

PlayerControls.svelte:

<script>
import PlayIcon from '../icons/PlayIcon.svelte';
import PauseIcon from '../icons/PauseIcon.svelte';
export let audio;
const onClick = () => {
if (audio?.paused) audio.play();
else audio.pause();
};
</script>
{#if audio?.paused}
<PlayIcon {onClick} />
{:else}
<PauseIcon {onClick} />
{/if}

如果按播放图标,图标不变,但开始播放音频,如果再次点击,音频停止,图标不变。好像是音频。停顿了一下"changes"只在脚本中,而不是在html中。这里有什么问题,我不明白的地方是什么?

在您给定的情况下,最健壮的解决方案是利用特定的<audio>元素事件来提醒svelte重新检查ref的状态。这允许svelte管理您的侦听器生命周期,并且还允许元素本身处理播放状态何时/如何更改的所有边缘情况。

<script>
import { onMount, onDestroy } from 'svelte';
import PlayerControls from './PlayerControls.svelte';
let audio;
const audioUpdated = (e) => {
audio = audio;
};
</script>
<audio
bind:this={audio}
src="https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
on:pause={audioUpdated}
on:play={audioUpdated}
on:ended={audioUpdated}
/>
<PlayerControls {audio} />

REPL

原始回答

您的问题的直接解决方案涵盖在我的评论反应性/更新数组和对象的文档链接中,并且简单地重新分配audio作为onClick处理程序的最后一步。

请记住,如果音频自己完成,这不会跟踪paused中的变化。

const onClick = () => {
if (audio?.paused) audio.play();
else audio.pause();

audio = audio;
};

REPL

编辑

我最初建议可以直接改变paused属性:

const onClick = () => {
if (audio?.paused) {
audio.play();
audio.paused = false;
} else {
audio.pause();
audio.paused = true;
}
};

但是忽略了audio是一个ref,paused是一个只读属性。

最新更新