Svelte: перемонтировать компонент для перезаписи медиа-элементов

  • Контекст

В моем приложении Svelte у меня есть несколько страниц, на каждой из которых отображается одно или несколько видеороликов. Для рендеринга видео я повторно использую видеокомпонент (упрощенный):

// 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 остается неизменным, в то время как изменяются только атрибуты и контент. Таким образом сохраняется состояние и уже буферизованный источник.

Мне как-то нужно было бы заверить, что при изменении данных видеокомпонент должен быть полностью перемонтирован. Кто-нибудь знает, как это сделать? Спасибо!


person moritzebeling    schedule 15.11.2019    source источник
comment
Мне нелогично, что старое воспроизведение все еще будет действовать при изменении источника. Показанный здесь фрагмент не является реактивным, как происходит загрузка нового источника?   -  person Félix Adriyel Gagnon-Grenier    schedule 15.11.2019
comment
Каждая ссылка на сайте запускает функцию, которая загружает данные из API для рендеринга новой страницы, включая видео. Я просто заменяю объект данных и все обновления содержимого, как ожидалось. За исключением видео, они остаются неизменными до тех пор, пока на новой странице также есть видео.   -  person moritzebeling    schedule 15.11.2019
comment
Хорошо я понял. Как правило, svelte не дублирует произвольно элементы, отсюда и мой вопрос. Однако показанный здесь сценарий не заменяет данные, и эта замена данных, вероятно, важна для решения проблемы. Можете ли вы добавить код к вашему вопросу? В противном случае можно использовать инспектор, чтобы увидеть, что на самом деле происходит с элементами. Если элементы видео дублируются, это будет ключом к пониманию того, что происходит.   -  person Félix Adriyel Gagnon-Grenier    schedule 15.11.2019


Ответы (2)


После некоторых проб и ошибок и с помощью @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().

person moritzebeling    schedule 15.11.2019

У меня была такая же проблема с <input type="file" ....> И я решил ее, используя:

let video = true:
function reMountVideo() {
  video = false; 
  setTimeout(() => video = true, 0);
} 

{#if video }
  <Video source={source} />
{/if}

Я не пробовал $ destroy

person voscausa    schedule 15.11.2019
comment
зачем использовать setTimeout вместо прямого переназначения true? - person Félix Adriyel Gagnon-Grenier; 15.11.2019
comment
Ставить в очередь истину после рендера. - person voscausa; 15.11.2019
comment
Куда мне позвонить reMountVideo()? Если я вызываю его из beforeUpdate() или afterUpdate(), он создает бесконечный цикл. - person moritzebeling; 15.11.2019
comment
Вы вызываете его только тогда, когда вы заменяете одно видео другим или после того, как закончили видео. Так что не всегда. - person voscausa; 15.11.2019