Показывать видео при загрузке (превышен максимальный размер стека вызовов) в VueJs - PullRequest
0 голосов
/ 31 декабря 2018

Я пытаюсь реализовать функциональность, когда пользовательская мышь выходит за div, будет воспроизводиться некоторое видео.У меня есть эти компоненты, которые отображаются 25 раз на странице

<LocationStripeItemComponent
        v-for="(l, index) in locations" :key="index" :location="l">
</LocationStripeItemComponent>

И внутри этого компонента есть следующий код

<template>
<div class="stripe__item card" @mouseover="previewTrailerVideo(true)" @mouseleave="previewTrailerVideo(false)">

    <div class="card__gradient"></div>
    <img :src="location.teaser_image" v-show="!hideImage"
         :alt="location.name" class="card__img"/>

    <div class="card__trailer_loading" v-show="miniTrailerLoading"></div>
    <video v-show="invokeMiniTrailerDiv" autoplay loop class="card__video" id="miniTrailer">
        <source :src="location.teaser_video">
    </video>
</div>
</template>

<script>
export default {
        name: 'LocationStripeItemComponent',
        props: {
            location: {
                type: Object,
                required: true
            }
        },
        data() {
            return {
                invokeMiniTrailerDiv: false,
                miniTrailerLoading: false,
                miniTrailerPlaying: false,
                hideImage: false
            }
        },
        methods: {
            previewTrailerVideo(showState) {
                if (showState) {

                    this.invokeMiniTrailerDiv = true;
                    this.miniTrailerLoading = true;

                    let video = document.getElementById('miniTrailer');
                    if (video.readyState === 4) {
                        this.miniTrailerLoading = false;
                        this.hideImage = true;
                        this.miniTrailerPlaying = true;
                    } else {
                       setTimeout(this.previewTrailerVideo(showState), 1000);
                    }
                } else {
                    this.invokeMiniTrailerDiv = false;
                    this.miniTrailerLoading = false;
                    this.miniTrailerPlaying = false;
                    this.hideImage = false;
                }
            },
        }
    };
</script>

И ошибка, которую я продолжаю получать,

Uncaught RangeError: Maximum call stack size exceeded
    at Object.reactiveSetter [as invokeMiniTrailerDiv] (vue.esm.js?efeb:998)
    at VueComponent.proxySetter [as invokeMiniTrailerDiv] (vue.esm.js?efeb:3300)
    at VueComponent.previewTrailerVideo (LocationStripeItemComponent.vue?2f13:93)
    at VueComponent.previewTrailerVideo (LocationStripeItemComponent.vue?2f13:102)
    at VueComponent.previewTrailerVideo (LocationStripeItemComponent.vue?2f13:102)
    at VueComponent.previewTrailerVideo (LocationStripeItemComponent.vue?2f13:102)
    at VueComponent.previewTrailerVideo (LocationStripeItemComponent.vue?2f13:102)
    at VueComponent.previewTrailerVideo (LocationStripeItemComponent.vue?2f13:102)
    at VueComponent.previewTrailerVideo (LocationStripeItemComponent.vue?2f13:102)
    at VueComponent.previewTrailerVideo (LocationStripeItemComponent.vue?2f13:102)

Я думаю, что проблема заключается здесь:

setTimeout(this.previewTrailerVideo(showState), 1000);

, потому что рекурсивная функция вызывается слишком много раз, но я не знаю, как еще я могу получить свой элемент видео, так как скрытпрежде чем кто-то добавить мышь над элементом.Есть ли другой способ определить, когда элемент виден на странице?Как правильно реализовать этот функционал?Танк ты!

1 Ответ

0 голосов
/ 31 декабря 2018

Задача 1

Неверный способ использования setTimeout.

Первый аргумент, который должен быть передан seTimeout, должен быть функцией.В вашем коде вы передаете undefined:

setTimeout(this.previewTrailerVideo(showState), 1000);

Поскольку функция previewTrailerVideo ничего не возвращает, что означает undefined.

Другими словами, ваш setTimeout неработает на всех.Это означает, что ошибка, которую вы получаете, не из setTimeout.

Задача 2

Ошибка, которую вы получаете, на самом деле от того, как вы используете setTimeout (но не setTimeout сам).В той же строке:

setTimeout(this.previewTrailerVideo(showState), 1000);

Хотя setTimeout не вызывается должным образом, ваша рекурсия работает отлично (вот где возникает ошибка), потому что в этой строке вы на самом деле вызываете Ваша функция, снова и снова, когда showState === true.

Решение

Просто отредактируйте эту строку в:

setTimeout(this.previewTrailerVideo.bind(this, showState), 1000);

Читать о.bind для подробностей.

Короче говоря, метод .bind не будет вызывать вашу функцию, но будет передавать аргументы в вашу функцию и возвращать вашу функцию с этими аргументами уже внутри.

Используя .bind, вы теперь передаете предполагаемую функцию в setTimeout (проблема 1), а также прекращаете повторение (проблема 2).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...