То, что я пытаюсь сделать, довольно просто: в моей таблице есть разбивка на страницы. Итак, если у меня есть 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 ответ
Работа с вашим кодом
Рефакторинг
Прежде всего, давайте выделим четкую и отдельную функцию
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));
Очень хорошо описано. Мне понравился твой ответ. Посмотрим на Lodash, это кажется хорошим фреймворком, в противном случае будет использоваться улучшенная версия, которую вы предоставили.
— Пеликер