...

Реализация Ленивая загрузка/Бесконечный скролл

Тема в разделе "Примеры решений и дополнительных модулей", создана пользователем ksannikov, 17 ноя 2025 в 12:50.

  1. ksannikov

    ksannikov Активный участник

    Я покажу пример реализации "Ленивой загрузки" данных или как ее называют по другому "Бесконечный скролл".

    Все подробности в ролике, а ниже код, который был использован в видео.

    Код с разметкой и функцией для отслеживания "якоря":

    HTML:
    <div class="news-list" id="content"></div>
    <div id="sentinel"></div>
    
    <script>
        function setObserver() {
            let sentinel = document.getElementById('sentinel');
            const observer = new IntersectionObserver(entries => {
                if (entries[0].isIntersecting) {
                    <%= Scripts %>.loadItems();
                }
            });
            observer.observe(sentinel);
        }
        setObserver()
        <%= Scripts %>.loadItems();
    </script>
    
    <template id="newsTemplate">
        <article class="news-card" aria-labelledby="title">
            <header class="news-header">
                <h2 class="news-title" id="title"></h2>
            </header>
            <figure class="news-figure">
                <img class="news-image" src="" alt=""/>
            </figure>
            <div class="news-body">
                <p></p>
            </div>
            <footer class="news-footer">
                <p class="news-date"></p>
            </footer>
        </article>
    </template>
    
    <style>
        .news-list {
            background-color: #F0F6FB;
            padding: 15px;
        }
    
        .news-card {
            background-color: #ffffff;
            padding: 15px;
            border: 1px solid #D9D9D9;
            border-radius: 5px;
            margin-bottom: 15px;
        }
    
        .news-title {
            margin: 0 0 12px 0;
            font-size: 18px;
            font-weight: 700;
        }
    
        .news-figure {
            margin: 0 0 12px 0;
        }
    
        .news-image {
            width: 100%;
            height: auto;
            display: block;
            border-radius: 8px;
            object-fit: cover;
        }
    
        .news-body p {
            margin: 0 0 12px 0;
            font-size: 14px;
            color: #374151;
        }
    
        .news-footer {
            margin-top: 8px;
            display: flex;
            justify-content: flex-end;
        }
    
        .news-date {
            font-size: rem;
        }
    </style>
    
    Код из вкладки "Скрипты":

    Код:
    
    declare const documentanyconsoleanywindowany
    /** Счетчик общего кол-ва новостей на странице */
    let count 0;
    /** Кол-во элементов для подгрузки */
    let amount_items 2;
    let end false

    async 
    function loadItems() {
        if (
    Context.data.loading || end) return
        
    Context.data.loading true;
        const 
    items await Namespace.app.news.search().from(count).size(amount_items).all()
        if (
    items.length == 0) {
            
    Context.data.loading false;
            
    end true
            
    return
        }
        
    await Promise.all(items.map(=> addNewsItem(f)))
        
    count += amount_items
        Context
    .data.loading false;
    }

    async function addNewsItem(itemBaseApplicationItem<anyany>) {
        const 
    tpl document.getElementById('newsTemplate');
        const 
    container document.getElementById('content');
        if (!
    tpl || !container) return;
        const clone = 
    tpl.content.cloneNode(true);
        const 
    titleEl = clone.querySelector('.news-title');
        
    titleEl.textContent item.data.__name;
        const 
    imgEl = clone.querySelector('.news-image');
        if (
    item.data.file) {
            
    imgEl.src await item.data.file.getDownloadUrl()
        } else {
            const 
    fig = clone.querySelector('.news-figure');
            
    fig && fig.remove();
        }
        const 
    textEl = clone.querySelector('.news-body p');
        
    textEl.textContent item.data.opisanie ?? '';
        const 
    timeEl = clone.querySelector('.news-date');
        
    timeEl.textContent item.data.__createdAt.format('DD.MM.YYYY hh:mm');

        
    container.appendChild(clone);
    }
    Еще больше полезной информации в ТГ канале WhatDaELMA365