разбивка на страницы

То, что я пытаюсь сделать, довольно просто: в моей таблице есть разбивка на страницы. Итак, если у меня есть 12 элементов, которые нужно показать, а мое максимальное количество элементов на странице равно 10, у меня будет 2 страницы, одна с 10 записями, а другая – всего с 2. Я создал код, который отлично работает, но кажется довольно грязным. Как лучше всего добиться того же результата, что и в приведенном ниже коде, но с меньшим количеством строк и более чистым? Я ищу меньше вложенности, меньше переменных, что бы упростило.

Примечание: props.content содержит все элементы;

let pagesContainer = [];
let page = [];
let i = 0;
for (const content of props.content) {
    if (i < itemsPerPage) {
        page.push(content);
        i++;
    } else {
        pagesContainer.push(page)
        page = [];
        page.push(content)
        i = 0;
    }
    if (props.content.indexOf(content) === props.content.length - 1) {
        pagesContainer.push(page);
    }
}
console.log(pagesContainer);

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

1 ответ
1

Работа с вашим кодом

Рефакторинг

Прежде всего, давайте выделим четкую и отдельную функцию

function getPaged(items, itemsPerPage) {
    let pagesContainer = [];
    let page = [];
    let i = 0;
    for (const content of items) {
        if (i < itemsPerPage) {
            page.push(content);
            i++;
        } else {
            pagesContainer.push(page)
            page = [];
            page.push(content)
            i = 0;
        }
        if (items.indexOf(content) === items.length - 1) {
            pagesContainer.push(page);
        }
    }
    
    return pagesContainer;
}

console.log(getPaged(props.content, itemsPerPage));

Теперь вы можете заметить, что переменная i всегда равно page.length. Так что нам это не нужно. Просто замените использование i с участием page.length:

function getPaged(items, itemsPerPage) {
    let pagesContainer = [];
    let page = [];
    for (const content of items) {
        if (page.length < itemsPerPage) {
            page.push(content);
        } else {
            pagesContainer.push(page)
            page = [];
            page.push(content);
        }
        if (items.indexOf(content) === items.length - 1) {
            pagesContainer.push(page);
        }
    }
    
    return pagesContainer;
}

console.log(getPaged(props.content, itemsPerPage));

Состояние if (items.indexOf(content) === items.length - 1) не мило. Нам действительно не нужно добавлять последнюю страницу внутри цикла. Давайте добавим эту страницу снаружи:

function getPaged(items, itemsPerPage) {
    let pagesContainer = [];
    let page = [];
    for (const content of items) {
        if (page.length < itemsPerPage) {
            page.push(content);
        } else {
            pagesContainer.push(page)
            page = [];
            page.push(content);
        }
    }
    
    if (page.length > 0) {
        pagesContainer.push(page);
    }
    
    return pagesContainer;
}

console.log(getPaged(props.content, itemsPerPage));

Нет причин создавать страницу и вставлять на нее новый элемент. Потому что мы можем создать страницу с новым элементом внутри.

function getPaged(items, itemsPerPage) {
    let pagesContainer = [];
    let page = [];
    for (const content of items) {
        if (page.length < itemsPerPage) {
            page.push(content);
        } else {
            pagesContainer.push(page)
            page = [content];
        }
    }
    
    if (page.length > 0) {
        pagesContainer.push(page);
    }
    
    return pagesContainer;
}

console.log(getPaged(props.content, itemsPerPage));

Украсить

Сделаем несколько переименований, чтобы жизнь стала короче:

  • itemsPerPage → pageSize
  • pagesContainer → страницы
  • контент → элемент

Также отметим, что переменная pages (ранее pagesContainer) не модифицируется. Итак, мы можем использовать const.

function getPaged(items, pageSize) {
    const pages = [];
    let page = [];
    for (const item of items) {
        if (page.length < pageSize) {
            page.push(item);
        } else {
            pages.push(page)
            page = [item];
        }
    }

    if (page.length > 0) {
        pages.push(page);
    }

    return pages;
}

console.log(getPaged(props.content, itemsPerPage));

Возможное улучшение

Мы можем создать ленивое решение с помощью генераторы.

function* getPaged(items, pageSize) {
    let page = [];
    for (const item of items) {
        if (page.length < pageSize) {
            page.push(item);
        } else {
            yield page;
            page = [item];
        }
    }

    if (page.length > 0) {
        yield page;
    }
}

console.log(Array.from(getPaged(props.content, itemsPerPage)));

Это круто только в том случае, если вам нужно лениво постобработать свои страницы.

Альтернативное решение 1

Наше альтернативное решение будет основано на функциональном нисходящем подходе. Сначала мы сгенерируем все страницы из 0 к pageCount; А затем мы заполним каждую страницу ее фактическим содержанием.

const range = (size) => [...Array(size).keys()];

function getPaged(items, pageSize) {
    const pageCount = Math.ceil(items.length / pageSize);
    
    const getPage = (pageNo) => range(pageSize)
        .map(noInPage => items[pageNo * pageSize + noInPage])
        .filter(item => item !== undefined);
    
    return range(pageCount)
        .map(pageNo => getPage(pageNo));
}

console.log(getPaged(props.content, itemsPerPage));

Обратите внимание, что это решение будет медленнее. Это потому что map а также filter медленные. Но это можно решить с помощью преобразователи

Альтернативное решение 2

Использовать lodash / кусок и не пишите свою собственную функцию

Альтернативное решение 3

С использованием lodash / groupBy, группируйте элементы по страницам. Затем верните только значения полученного словаря.

const getPaged = (items, pageSize) => 
    Object.values(_.groupBy(
    items,
    (item, index) => Math.floor(index / pageSize)
  ));

console.log(getPaged(props.content, itemsPerPage));

  • 1

    Очень хорошо описано. Мне понравился твой ответ. Посмотрим на Lodash, это кажется хорошим фреймворком, в противном случае будет использоваться улучшенная версия, которую вы предоставили.

    – Пеликер

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *