Индикаторы загрузки

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

Механизм асинхронных операций в Marko

Для реализации индикаторов загрузки в Marko важно понимать, как работает обработка асинхронных данных. Основной принцип заключается в том, что Marko использует серверное рендеринг (SSR) и клиентскую встраиваемую логику. Это означает, что сервер может отправить HTML с начальным состоянием, а JavaScript на клиенте управляет динамическими изменениями.

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

Использование флагов загрузки

Наиболее простой и часто используемый способ — это создание флага загрузки, который можно отображать в интерфейсе до тех пор, пока не будут загружены все необходимые данные.

Пример:

<template>
    <div>
        <if(test=loading)>
            <div class="spinner">Загрузка...</div>
        </if>
        <div>
            <span>Данные загружены!</span>
        </div>
    </div>
</template>

<script>
    export default class {
        onCreate() {
            this.loading = true;
            this.fetchData().then(() => {
                this.loading = false;
            });
        }

        async fetchData() {
            // Имитируем задержку при загрузке данных
            await new Promise(resolve => setTimeout(resolve, 2000));
        }
    }
</script>

Здесь создается условие с флагом loading, который по умолчанию равен true. Пока данные загружаются, отображается индикатор загрузки в виде простого текста или элемента (например, анимации). Когда загрузка данных завершена, флаг изменяется, и показывается основной контент.

Интерактивные индикаторы загрузки

Использование анимаций или более сложных индикаторов — распространенная практика для улучшения пользовательского опыта. Marko позволяет интегрировать сторонние библиотеки или кастомные компоненты для отображения таких индикаторов. В случае использования простых CSS-анимированных элементов можно подключить их непосредственно к компоненту.

Пример с анимацией загрузки:

<template>
    <div>
        <if(test=loading)>
            <div class="loader"></div>
        </if>
        <div>
            <span>Данные успешно загружены!</span>
        </div>
    </div>
</template>

<style>
    .loader {
        border: 16px solid #f3f3f3; /* Light grey */
        border-top: 16px solid #3498db; /* Blue */
        border-radius: 50%;
        width: 120px;
        height: 120px;
        animation: spin 2s linear infinite;
    }

    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }
</style>

<script>
    export default class {
        onCreate() {
            this.loading = true;
            this.fetchData().then(() => {
                this.loading = false;
            });
        }

        async fetchData() {
            await new Promise(resolve => setTimeout(resolve, 2000));
        }
    }
</script>

Этот пример использует CSS-анимированную круговую загрузку. Такое визуальное представление индикатора более заметно и дает пользователю понять, что приложение обрабатывает запрос. Важно также учитывать, что анимации могут быть выполнены как с использованием CSS, так и через JavaScript с динамическим изменением стилей.

Управление асинхронными компонентами

Когда необходимо загружать не только данные, но и целые компоненты (например, динамически подгружаемые блоки или страницы), можно использовать асинхронные компоненты Marko. Для этого достаточно обернуть компонент в асинхронную функцию и отображать индикатор загрузки, пока компонент не станет доступен.

Пример:

<template>
    <div>
        <if(test=loading)>
            <div class="spinner">Загрузка компонента...</div>
        </if>
        <async-component if(test=loaded) />
    </div>
</template>

<script>
    import AsyncComponent from './AsyncComponent.marko';

    export default class {
        onCreate() {
            this.loading = true;
            this.loaded = false;
            this.loadComponent();
        }

        async loadComponent() {
            await new Promise(resolve => setTimeout(resolve, 2000)); // Задержка для имитации загрузки
            this.loaded = true;
            this.loading = false;
        }
    }
</script>

Здесь компонент AsyncComponent загружается асинхронно. Пока он не загружен, показывается индикатор, который заменяется на сам компонент, как только он будет доступен.

Гибкость использования

Одним из ключевых достоинств Marko является его гибкость. Использование индикаторов загрузки можно адаптировать под разные требования проекта. Например, можно сочетать индикаторы для различных типов данных или компонентов, а также использовать различные способы отображения информации в зависимости от сложности задачи.

Пример с несколькими индикаторами загрузки:

<template>
    <div>
        <if(test=loadingData)>
            <div class="loader">Загрузка данных...</div>
        </if>
        <if(test=loadingComponent)>
            <div class="spinner">Загрузка компонента...</div>
        </if>
        <div>
            <span>Данные и компоненты загружены!</span>
        </div>
    </div>
</template>

<script>
    export default class {
        onCreate() {
            this.loadingData = true;
            this.loadingComponent = true;
            this.loadData();
            this.loadComponent();
        }

        async loadData() {
            await new Promise(resolve => setTimeout(resolve, 2000)); // Задержка при загрузке данных
            this.loadingData = false;
        }

        async loadComponent() {
            await new Promise(resolve => setTimeout(resolve, 2000)); // Задержка при загрузке компонента
            this.loadingComponent = false;
        }
    }
</script>

Здесь используется два отдельных флага загрузки для данных и компонентов, что позволяет контролировать отображение различных индикаторов одновременно. Такой подход полезен, если нужно точно управлять состоянием загрузки различных частей приложения.

Заключение

Реализация индикаторов загрузки в Marko проста и гибка. Возможности фреймворка позволяют легко внедрять как простые статические индикаторы, так и сложные анимации с динамическими данными. Использование флагов состояния и асинхронных методов открывает множество вариантов для отображения процессов загрузки, что улучшает взаимодействие пользователя с приложением.