Я сделал кодовый блок моей проблемы здесь https://codepen.io/stevemr/pen/VNQbYe
У меня есть корневой экземпляр Vue, который поддерживает реквизиты для компонента, VideoPlayer. В моем корневом экземпляре есть метод setVideo, который прямо сейчас присваивает некоторые фиктивные значения.
Вот объект, который я использую в данных корневого экземпляра:
video: {
drive: '',
filename: '',
mediaType: '',
},
Вот функция setVideo:
setVideo: function() {
// Get the drive, filename, and mediaType
this.video.drive = 'hdd1';
this.video.filename = 'game-of-thrones_s01e04.mp4';
this.video.mediaType = 'show';
// Hide all modals and trigger the display of the video player
Event.trigger('hideModal');
Event.trigger('displayVideoPlayer');
},
Класс Event - это просто оболочка для основных событий Vue:
window.Event = new class {
constructor() {
this.vue = new Vue();
}
trigger(event, data = null) {
this.vue.$emit(event, data);
}
listen(event, callback) {
this.vue.$on(event, callback);
}
};
Вот DOM, где инициализирован мой компонент VideoPlayer:
<video-player
v-bind:drive="video.drive"
v-bind:filename="video.filename"
v-bind:media-type="video.mediaType"
></video-player>
И, наконец, вот мой компонент VideoPlayer:
<template>
<div>
<div id="movie-container">
<div
class="video-loader top-most"
v-if="showVideoPlayer && !loaded"
></div>
<video
id="video-player"
ref="video"
v-if="showVideoPlayer && src !== ''"
class="top-most"
v-bind:class="{ hidden: !loaded }"
v-on:click="togglePlay"
controls
autoplay
>
<source v-bind:src="src" v-bind:type="videoType"></source>
</video>
</div>
<div id="time-range-container" v-if="showTimeRange">
<input
id="time-range"
ref="timeRange"
type="range"
min="0"
v-bind:max="duration"
step="30"
v-model:value="currentTime"
/>
</div>
</div>
</template>
<script>
export default {
props: [
'drive',
'filename',
'mediaType',
],
data() {
return {
currentTime: 0,
duration: 0,
loaded: false,
showTimeRange: false,
showVideoPlayer: false,
}
},
computed: {
src: function() {
if(this.filename !== '') {
return
'/video/' + this.drive +
'/' + this.mediaType +
's/' + this.filename;
}
return '';
},
videoType: function() {
var ext = this.filename.split('.')[1];
var type = '';
switch(ext) {
case 'mk4':
case 'm4v':
type = 'webm';
break;
case 'avi':
type = 'ogg';
break;
default:
type = ext;
}
return 'video/' + type;
},
},
created() {
Event.listen('displayVideoPlayer', this.display);
},
methods: {
display: function() {
if(this.src === '') {
return;
}
this.showVideoPlayer = true;
this.loaded = false;
var self = this;
setTimeout(function() {
var interval = setInterval(function() {
var video = self.$refs.video;
if(video.readyState > 0) {
self.loaded = true;
self.duration = Math.round(video.duration);
self.currentTime = video.currentTime;
clearInterval(interval);
}
}, 500);
}, 800);
},
togglePlay: function() {
var video = this.$refs.video;
if(video.paused) {
video.play();
}
if(!video.paused) {
video.pause();
}
},
},
}
</script>
Когда вызывается setVideo, он должен установить реквизиты компонента VideoPlayer на фиктивные значения, после чего должен отображаться видеоплеер. Но вместо этого, когда происходит событие displayVideoPlayer, для компонентов компонента все еще устанавливаются значения по умолчанию (пустые строки). Самое главное, что вычисляемое свойство src не обновляется до вызова метода display, поэтому функция display сразу же возвращается, ничего не делая.
Похоже, что реквизиты и данные моего компонента не обновляются, хотя я могу видеть с помощью инструментов dev, что они есть. Как будто это происходит недостаточно быстро или что-то в этом роде.
Я попытался сделать src частью данных компонента и установить его в функции отображения с помощью другой функции setSrc. Но случилось то же самое.
Я также пытался переместить Event.listen ('displayVideoPlayer', this.display); в mount () вместо create () тоже ничего не исправил.
Если вы посмотрите на кодовую ручку, то при первом нажатии кнопки для запуска функции setVideo должен отображаться компонент видеопроигрывателя, вместо этого требуется 2 щелчка.