Svelte:重新安装组件以覆盖媒体元素
Svelte: Remount component to overwrite media elements
- 上下文
在我的 Svelte 应用中,我有多个页面,每个页面显示一个或多个视频。
为了渲染视频,我重复使用了 video 组件(简化):
// video component
<video poster="{source.thumb}">
<source type="{source.mime}" src="{source.source}" >
</video>
主页通过api接收视频内容并调用视频组件:
// calling video component on main page
<script>
let source = {
thumb: 'thumb.jpg',
source: 'video.mp4',
mime: 'video/mp4',
};
</script>
<Video source={source} />
一切正常,视频已渲染并可以播放。
- 问题
但是: 当我导航或想用另一个视频替换视频时,旧视频元素仍然存在并且播放继续。
我可以使用 beforeUpdate()
暂停视频。但是随后,新视频奇怪地在完全相同的播放时间加载,一切都混淆了。或者,如果我删除 beforeUpdate()
中的视频元素,它不会填充新信息。
这有点道理,因为 video
媒体元素保持完全相同,只有属性和内容发生变化。因此状态和已经缓冲的源仍然存在。
不知何故我需要保证,当数据发生变化时,必须完全重新安装视频组件。
有谁知道这是怎么做到的吗?谢谢!
我遇到了与 <input type="file" ....>
相同的问题
并使用以下方法解决:
let video = true:
function reMountVideo() {
video = false;
setTimeout(() => video = true, 0);
}
{#if video }
<Video source={source} />
{/if}
我没试过$destroy
经过反复试验并在@voscausa 的帮助下,它现在可以工作了:
<script>
export let source;
let renderVideo = true;
$: { reMountVideo( source.source ) }
function reMountVideo(){
renderVideo = false;
setTimeout(() => renderVideo = true, 0);
}
</script>
{#if renderVideo === true}
<video poster="{source.thumb}">
<source type="{source.mime}" src="{source.source}" >
</video>
{/if}
它检查视频 url 是否发生变化,如果发生变化,则触发 reMountVideo()
。
当前版本的 svelte 支持这个。每次 属性 src
更改时,都会在 video
上附加一个回调。
<script>
let src = ...
function load(node, src){
if(src){
node.src = src;
node.load();
}
return {
update(src){
if(src){
node.src = src;
node.load();
}
}
}
}
</script>
<video use:load={src}>
要在源更改时触发视频的重新渲染,{#key} block could be used REPL
<script>
export let source;
</script>
{#key source}
<video poster="{source.thumb}" controls>
<source type="{source.mime}" src="{source.source}" >
</video>
{/key}
- 上下文
在我的 Svelte 应用中,我有多个页面,每个页面显示一个或多个视频。 为了渲染视频,我重复使用了 video 组件(简化):
// video component
<video poster="{source.thumb}">
<source type="{source.mime}" src="{source.source}" >
</video>
主页通过api接收视频内容并调用视频组件:
// calling video component on main page
<script>
let source = {
thumb: 'thumb.jpg',
source: 'video.mp4',
mime: 'video/mp4',
};
</script>
<Video source={source} />
一切正常,视频已渲染并可以播放。
- 问题
但是: 当我导航或想用另一个视频替换视频时,旧视频元素仍然存在并且播放继续。
我可以使用 beforeUpdate()
暂停视频。但是随后,新视频奇怪地在完全相同的播放时间加载,一切都混淆了。或者,如果我删除 beforeUpdate()
中的视频元素,它不会填充新信息。
这有点道理,因为 video
媒体元素保持完全相同,只有属性和内容发生变化。因此状态和已经缓冲的源仍然存在。
不知何故我需要保证,当数据发生变化时,必须完全重新安装视频组件。 有谁知道这是怎么做到的吗?谢谢!
我遇到了与 <input type="file" ....>
相同的问题
并使用以下方法解决:
let video = true:
function reMountVideo() {
video = false;
setTimeout(() => video = true, 0);
}
{#if video }
<Video source={source} />
{/if}
我没试过$destroy
经过反复试验并在@voscausa 的帮助下,它现在可以工作了:
<script>
export let source;
let renderVideo = true;
$: { reMountVideo( source.source ) }
function reMountVideo(){
renderVideo = false;
setTimeout(() => renderVideo = true, 0);
}
</script>
{#if renderVideo === true}
<video poster="{source.thumb}">
<source type="{source.mime}" src="{source.source}" >
</video>
{/if}
它检查视频 url 是否发生变化,如果发生变化,则触发 reMountVideo()
。
当前版本的 svelte 支持这个。每次 属性 src
更改时,都会在 video
上附加一个回调。
<script>
let src = ...
function load(node, src){
if(src){
node.src = src;
node.load();
}
return {
update(src){
if(src){
node.src = src;
node.load();
}
}
}
}
</script>
<video use:load={src}>
要在源更改时触发视频的重新渲染,{#key} block could be used REPL
<script>
export let source;
</script>
{#key source}
<video poster="{source.thumb}" controls>
<source type="{source.mime}" src="{source.source}" >
</video>
{/key}