Предварительная загрузка изображений в Vue с помощью Vue Router - PullRequest
0 голосов
/ 10 июля 2019

Немного предыстории ...

Давным-давно я написал простой плагин JS, который автоматически удаляет источники изображения со страницы и предварительно загружает каждый из них перед последующим отображением содержимого страницы.т.е. показывать счетчик или индикатор выполнения, а затем показывать основное содержимое.

Однако сейчас я собираюсь добавить именно эту функциональность в мои проекты Vue с намерением разрешить каждому view предварительно загружать каждое из изображений.в их относительных DOM.

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

Моя структура и планируемая реализация

Каждый из моих проектов Vue имеет следующую иерархию компонентов:

App.vue -> {route}.vue -> {relevant components}.vue

Исходя из этого, я придумал следующую структуру:

App.vue

  • Хранить локальный логический loaded, который определит, отображать ли содержимое (router-view) или spinner
  • Сохранить локальный массив images чтобы сохранить все изображения для предварительной загрузки
  • Определить метод preload, который будет проходить по циклу и предварительно загружать все изображения
  • Прослушать изменения loaded, например, когда loadedis false вызывает метод preload
  • Прослушивание изменений в images - это позволит нам объединить наши очищенные изображения DOM с нашим пользовательским списком изображений, излучаемых из {route}.vue компонентов

{route} .vue - через mixin

  • Зарегистрировать images проп, который будет определен на маршруте и будет выдавать эти значения в App.vue.
  • Зарегистрируйте loaded реквизит, который будет изменен на false до изменения маршрута

Мой код

Я началвнедряя это в мой код следующим образом (лишено только показывать релевантную информацию):

App.vue

<template>

    <div id="app" :class="{ loading: !loaded }">

        <!-- Main content loading indicator -->
        <spinner v-if="!loaded"></spinner>

        <!-- Main content wrapper -->
        <div id="main-wrapper">

            <!-- Include the main site header -->
            <main-header></main-header>

            <!-- Include the content of the current page -->
            <router-view :loaded.sync="loaded" :images.sync="images"></router-view>

            <!-- Include the main site footer -->
            <main-footer></main-footer>

        </div>

    </div>

</template>

<script>

    import Header from 'core-js/components/core/Header';
    import Footer from 'core-js/components/core/Footer';

    export default {

        components: {
            'main-header': Header,
            'main-footer': Footer
        },

        data() {
            return {
                images: [],
                loaded: false
            }
        },

        mounted() {

            // Trigger the preload once all components are mounted
            this.$nextTick(this.preload);

        },

        watch:{

            images(value) {

                // Whenever images is updated, we should merge with the
                // DOM scraped images
                console.log(value);

            },

            loaded(value) {

                // Whenever loaded is updated, we should hide and content
                // and show the spinner (if it is false)
                console.log(value);

            }

        },

        methods: {

            /**
             * Preload all images for the active route.
             *
             * @return void
             */
            preload() {

                // Scrape the DOM and build array of images
                // Then merge this array with `this.images`

                // For testing purposes...
                setTimeout(() => { this.loaded = true; }, 2000);

            }

        }

    }

</script>

PreloadRoute.js (mixin)

export default {

    props: {

        loaded: {
            type: Boolean,
            required: false
        },

        images: {
            type: Array,
            required: false
        }

    },

    beforeRouteEnter(to, from, next) {
        console.log('The route is about to change');
    }

};

Мой вопрос

Как видно из приведенного выше кода, это очень большой прогресс, так как я столкнулся с проблемой, которую я не совсем уверен, как

В миксине PreloadRoute.js мне нужно сообщить App.vue, что loaded теперь ложно.Однако мне нужно сделать это до того, как маршрут действительно изменится.Поскольку this недоступно в beforeRouteEnter, я не могу передать изменения.Я не могу использовать next, потому что он мне особенно нужен для запуска до того, как маршрут действительно изменится.

Есть ли способ передать изменение реквизита в родительский компонент до того, как дочерний компонент фактически инициализирован?

Я думал о возможном использовании отдельного экземпляра Vue в качестве шины событий, например так:

window.bus = new Vue();

Я забочусь об этом, я считаю, что это можно сделать лучше ...

Дополнительно...

Причина, по которой я включил все вышеперечисленное содержимое, а не просто вопрос относительно beforeRouteEnter, заключается в том, что я открыт для альтернативных структурных предложений.Другими словами, если у вас есть предложения относительно более простой / альтернативной структуры, которая позволит достичь того, что я ищу, тогда, пожалуйста, во что бы то ни стало, стреляйте ...

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