
Как создавать страницы с разбивкой на страницы на GatsbyJS с элементами управления разбиением на страницы
Добро пожаловать в блог! В этом посте мы рассмотрим, как добавить нумерацию страниц на веб-сайт GatsbyJS.
К концу этого поста:
- Ваш веб-сайт сможет создавать необходимые страницы для размещения всего вашего контента.
- Количество страниц будет определяться количеством сообщений, которые мы хотим на странице.
- Наконец, мы добавим элементы управления для перехода между страницами с возможностью перехода на определенную страницу.
Что мы создаем?
Ниже приведен снимок экрана с моего действующего сайта conermurphy.com. Сегодня мы рассмотрим функциональность, которая позволяет нам указать, что я хочу X сообщений на страницу, а затем попросить Гэтсби создать эти страницы для нас. В этом руководстве я буду использовать блог в качестве примера, но эта логика может применяться к любой странице на веб-сайте. Например, я также использую его в своих заметках на сайте.
Что мы закончим, так это приведенная ниже структура URL:
- yourURL.com/blog/ ‹- Сообщения 19–24
- yourURL.com/blog/1 ‹- Сообщения 13-18
- yourURL.com/blog/2 ‹- Сообщения 7–12
- yourURL.com/blog/3 ‹- Сообщения 1-6
Проверить это:

Предпосылки
Итак, что вам нужно сделать перед тем, как приступить к работе с этим руководством?
Пока у вас есть рабочий блог с несколькими сообщениями, вам будет хорошо. В рамках этого руководства я не буду рассказывать, как настроить источник контента в Gatsby. Или как создавать отдельные сообщения в блоге с помощью файла шаблона. Но, если вы заинтересованы в этих уроках, дайте мне знать.
Пока у вас есть одна страница, на которой есть все ваши сообщения, вам будет хорошо. 😃
Если вы впервые хотите создать свой блог, LogRocket предлагает вам отличное руководство.
Гэтсби-узел
Хорошо, разобравшись со всем этим, давайте приступим к написанию кода.
Как упоминалось выше, наши сообщения уже должны быть отправлены в Gatsby в файле gatsby-node.js. После этого они должны отображаться в виде одного длинного списка.
Если ваша индивидуальная генерация страницы сообщений уже настроена, у вас должен быть хук в createPages API. Если нет, то вот краткий обзор.
CreatePages
createPages - это API узла Gatsby, который позволяет динамически создавать страницы. Этот API запускается после поиска и преобразования узлов и завершения создания схемы GraphQL. "Об этом подробнее здесь."
В следующих примерах кода я использую модули ES6 в моем файле gatsby-node, по умолчанию они не включены. Вы можете воспользоваться инструкцией, которую я написал в Твиттере, чтобы настроить их.
Чтобы начать настройку createPages API и создание страниц с разбивкой на страницы, нам нужно добавить приведенный ниже код.
export async function createPages(params) {
await Promise.all([turnBlogPostsIntoPages(params)]);
}
Это позволяет нам подключиться к API createPages. Promise.all не требуется, вы можете добавить весь код в эту одну функцию. Но для удобства чтения я разделил отдельные поколения на их собственные функции.
Чтобы проиллюстрировать этот момент, вот прямая копия с моего текущего веб-сайта:
export async function createPages(params) {
// After the creation of the nodes create pages for each custom type.
await Promise.all([
// Blog Posts
turnBlogPostsIntoPages(params),
// Notes Pages
turnNotesIntoPages(params),
// Turn sourced Twitter Threads into pages.
turnTwitterThreadsIntoPages(params),
// Blog Tags Pages
turnBlogPostTagsIntoPages(params),
// Turn Notes Categories into pages
turnNotesCategoriesIntoPages(params),
// Turn Twitter Threads Tags Into Pages
turnThreadsTagsIntoPages(params),
// Turn Portfolio Tags into pages
turnPortfolioTagsIntoPages(params),
// Turn Read Categories into pages.
turnReadsCategoriesIntoPages(params),
]);
}
Если я помещу все эти функции в функцию createPages, она будет иметь длину более 300 строк. Это определенно плохо для нашей читабельности.
Во всяком случае, вернемся к теме. Затем нам нужно создать объявленную функцию turnBlogPostsIntoPages.
Итак, где-нибудь над этой createPages функцией добавьте новую функцию, например:
async function turnBlogPostsIntoPages({ graphql, actions }) {
const { createPage } = actions;
}
export async function createPages(params) {
await Promise.all([turnBlogPostsIntoPages(params)]);
}
Теперь у нас есть функция, которая вызывается при запуске createPages API. Давайте углубимся в эту функцию и начнем заставлять ее делать что-нибудь полезное.
Вот готовый код, который мы разберем через секунду.
async function turnBlogPostsIntoPages({ graphql, actions }) {
// 0: Destructuring out the action createPage which is used to create the pages.
const { createPage } = actions;
// 1: Query for all of blog post data. Most importantly the totalCount which we will use later on.
const {
data: {
blog: { edges: blogPosts, totalCount: blogTotalCount },
},
} = await graphql(`
query {
blog: allMdx(filter: { fields: { contentCategory: { eq: "blog" } } }) {
edges {
node {
fields {
slug
contentCategory
}
frontmatter {
title
date(formatString: "DD/MM/YYYY")
}
}
}
totalCount
}
}
`);
// 2: Create a page for every blog post node. (This is for indivual blog posts.)
blogPosts.forEach(({ node }, index) => {
createPage({
path: node.fields.slug,
component: path.resolve("./src/templates/Blog.js"),
context: {
slug: node.fields.slug,
prev: index === 0 ? null : blogPosts[index - 1].node,
next: index === blogPosts.length - 1 ? null : blogPosts[index + 1].node,
},
});
});
// 3: Create the main blog pages containing the posts..
const blogTemplate = path.resolve("./src/pages/blog.js");
const pageSize = 6; // Total number of posts on each page
const pageCount = Math.ceil(blogTotalCount / pageSize); // Total number of pages required.
// Loop through each page required (1 to x) and create a new blog page for each.
Array.from({ length: pageCount }).forEach((_, i) => {
createPage({
path: `/blog/${i === 0 ? "" : i + 1}`,
blogTemplate,
// Context is passed to the page so we can skip the required amount of posts on each page.
context: {
skip: i * pageSize,
currentPage: i + 1,
pageSize,
},
});
});
}
Если вы завершили настройку блога на GatsbyJS, возможно, у вас уже есть код, похожий на этот. Давайте разберем каждый шаг и посмотрим, что происходит.
- Здесь мы деструктурируем действие createPage. Это используется для фактического создания страниц на основе предоставляемой нами информации.
- Мы запрашиваем всю информацию, относящуюся к сообщениям, полученным с помощью GraphQL. Наиболее важно число
totalCount, поскольку оно используется для определения количества страниц, которые нам понадобятся позже. - Здесь отдельные сообщения в блоге создаются с помощью действия createPage, которое мы деструктурировали выше.
- Это шаг, который нас интересует в этом уроке. Здесь мы создаем постраничные сообщения блога. Давайте разберем это более подробно ниже.
Разбивка на страницы
Вот код, который нас особенно интересует в этом руководстве:
const blogTemplate = path.resolve("./src/pages/blog.js");
const pageSize = 6; // Total number of posts on each page
const pageCount = Math.ceil(blogTotalCount / pageSize); // Total number of pages required.
// Loop through each page required (1 to x) and create a new blog page for each.
Array.from({ length: pageCount }).forEach((_, i) => {
createPage({
path: `/blog/${i === 0 ? "" : i + 1}`,
blogTemplate,
// Context is passed to the page so we can skip the required amount of posts on each page.
context: {
skip: i * pageSize,
currentPage: i + 1,
pageSize,
},
});
});
Давайте посмотрим, что здесь происходит.
const blogTemplate = path.resolve("./src/pages/blog.js");
Сначала мы импортируем файл шаблона, который будем использовать для создания всех страниц с разбивкой на страницы. Обратите внимание, что это фактическая страница блога в каталоге ваших страниц. Не тот файл, который используется для создания отдельных сообщений, находящихся в папке шаблонов.
const pageSize = 6; // Total number of posts on each page
const pageCount = Math.ceil(blogTotalCount / pageSize); // Total number of pages required.
После этого мы создадим еще две переменные, которые будут контролировать размер страницы и количество необходимых страниц. Это достигается путем установки переменной pageSize на количество сообщений, которые мы хотим на каждой странице. Затем мы используем эту переменную, чтобы определить, сколько страниц нам нужно.
Мы достигаем этого, взяв totalnumber из нашего запроса graphQL и разделив его на размер страницы. Округляя этот результат, мы узнаем, сколько страниц нам нужно.
Дальше переходим к пикантной части:
// Loop through each page required (1 to x) and create a new blog page for each.
Array.from({ length: pageCount }).forEach((_, i) => {
createPage({
path: `/blog/${i === 0 ? "" : i + 1}`,
blogTemplate,
// Context is passed to the page so we can skip the required amount of posts on each page.
context: {
skip: i * pageSize,
currentPage: i + 1,
pageSize,
},
});
});
Что тут происходит?
Самая важная часть этого - то, что происходит в строке 2. Это та часть, которая позволяет нам создавать несколько страниц блога.
Array.from({ length: pageCount }).forEach((_, i) => {});
У нас есть переменная, которая сообщает нам, сколько страниц нам нужно (pageCount). Но для того, чтобы это было полезно для нас, мы должны иметь возможность перебирать все числа, ведущие к этой точке. Это позволит нам создать отдельную страницу для каждого номера.
Вот где появляется приведенная выше строка. Мы используем Array.from({ length: pageCount }) для создания массива с длиной, равной количеству страниц, которые нам нужно создать. Да, элементы массива будут пустыми, но это не имеет значения, потому что нас интересуют только индексы.
Чтобы получить доступ к индексам, мы подключаемся к Array.from() с .forEach((_, i) => {}), как показано выше. Поскольку нас интересуют только индексы, мы можем пропустить первый аргумент forEach. Это будет представлять фактический элемент (пустой) для индекса, который мы сейчас используем в массиве. Затем это позволяет нам получить доступ ко второму аргументу, который представляет индекс текущего элемента.
Теперь мы можем перебирать массив переменной длины, чтобы создать необходимое количество страниц. Теперь нам нужно заняться созданием.
Что мы можем сделать с помощью следующего кода:
createPage({
path: `/blog/${i === 0 ? "" : i + 1}`,
component: blogTemplate,
// Context is passed to the page so we can skip the required amount of posts on each page.
context: {
skip: i * pageSize,
currentPage: i + 1,
pageSize,
},
});
Давайте разберемся, что здесь происходит.
Мы передаем ряд аргументов действию createPage, это:
- path: URL-адрес, для которого будет создана страница.
- компонент: это файл, который будет использоваться для создания шаблона страницы.
- контекст: объект, содержащий данные, передаваемые на страницу.
- skip: мы передаем это, чтобы сообщить странице, сколько сообщений нужно пропустить в запросе GraphQL. Мы решаем это, умножая текущий индекс элемента, на котором мы находимся, на размер страницы. Итак, страница 1 будет:
0 * 6 = 0, а для страницы 2 -1 * 6 = 6. Это гарантирует, что мы пропустим правильное количество сообщений для каждой страницы. - currentPage: сообщает странице, какая это страница в настоящее время, которую мы будем использовать для навигации позже.
- pageSize: размер страницы, которую мы определили.
currentPage контекстные данные будут иметь больше смысла в последнем разделе этого сообщения в блоге. Это когда мы рассмотрим создание элементов управления разбиением на страницы для перемещения между страницами, которые мы создали. Но теперь давайте посмотрим, какие изменения нужно внести в файл подкачки, чтобы он мог использовать переданный нами контекст skip и pageSize.
Внесение изменений в файл подкачки
Теперь у нас есть файл gatsby-node.js, и мы готовы создавать для нас все страницы. Теперь нам нужно внести поправки в файл подкачки, в котором перечислены все сообщения для нас.
Обновление запроса GraphQL
Во-первых, нам нужно обновить запрос GraphQL, который выполняется на странице. У вас уже должно быть что-то вроде этого:
export const query = graphql`
query {
blog: allMdx(
sort: {
order: [DESC, DESC]
fields: [frontmatter___date, frontmatter___id]
}
filter: { fields: { contentCategory: { eq: "blog" } } }
) {
edges {
node {
fields {
slug
}
frontmatter {
date(formatString: "DD/MM/YYYY")
tags
title
id
image {
childImageSharp {
fluid(maxWidth: 400) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
totalCount
}
}
`;
Важно отметить, что в этом запросе мы получаем все сообщения блога. На данный момент для запроса нет никаких ограничений, кроме фильтра, который я сделал для выбора всего содержимого блога.
Теперь давайте посмотрим, что нам нужно добавить.
Помните, когда мы редактировали файл gatsby-node.js, мы передавали на страницу несколько фрагментов контекста? В первую очередь skip и pageSize. Поскольку мы передали их в качестве контекста на страницу, они доступны нам для использования в GraphQL в качестве переменных.
Давайте посмотрим на измененный запрос, а затем разберем его:
export const query = graphql`
query($skip: Int = 0, $pageSize: Int = 6) {
blog: allMdx(
limit: $pageSize
skip: $skip
sort: {
order: [DESC, DESC]
fields: [frontmatter___date, frontmatter___id]
}
filter: { fields: { contentCategory: { eq: "blog" } } }
) {
edges {
node {
fields {
slug
}
frontmatter {
date(formatString: "DD/MM/YYYY")
tags
title
id
image {
childImageSharp {
fluid(maxWidth: 400) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
totalCount
}
}
`;
Как вы можете видеть в верхней строке запроса, мы добавили две переменные, которые мы передали в качестве контекста. Давайте посмотрим на эту строку более подробно:
query($skip: Int = 0, $pageSize: Int = 6 ) {
Если вы не знакомы с синтаксисом GraphQL. Ниже представлен краткий обзор происходящего.
- $ skip: это имя переменной
- Int: это тип данных, к которым относится переменная.
- = 0: это значение переменной по умолчанию.
Итак, в этой строке мы берем две переменные, которые являются целыми числами (Ints), и присваиваем им значение по умолчанию.
Теперь давайте посмотрим, где они используются в запросе:
query($skip: Int = 0, $pageSize: Int = 6 ) {
blog: allMdx(
limit: $pageSize
skip: $skip
sort: { order: [DESC, DESC], fields: [frontmatter___date, frontmatter___id] }
filter: { fields: { contentCategory: { eq: "blog" } } }
)
// Rest of the query goes here...
}
Как видите, мы добавили переменные skip и pageSize. Они передаются в свойства skip и limit запроса.
Если бы мы преобразовали это в фактические значения страницы 1, это выглядело бы так:
query($skip: Int = 0, $pageSize: Int = 6 ) {
blog: allMdx(
limit: 6
skip: 0
sort: { order: [DESC, DESC], fields: [frontmatter___date, frontmatter___id] }
filter: { fields: { contentCategory: { eq: "blog" } } }
)
// Rest of the query goes here...
}
Это потому, что мы хотим ограничить результаты до 6 значений и пропускаем 0, потому что мы на первой странице. Если бы мы взглянули на страницу 2 в качестве примера, мы могли бы начать видеть, как это работает.
query($skip: Int = 0, $pageSize: Int = 6 ) {
blog: allMdx(
limit: 6
skip: 6
sort: { order: [DESC, DESC], fields: [frontmatter___date, frontmatter___id] }
filter: { fields: { contentCategory: { eq: "blog" } } }
)
// Rest of the query goes here...
}
Единственное, что изменилось, - это значение пропуска. Теперь вместо того, чтобы пропускать 0 значений, мы пропускаем первые 6. Затем мы возвращаем максимум 6 значений, начиная с элемента 7 в наборе данных.
Это повторяется для каждой страницы, которую мы генерируем, пока мы не охватим все сообщения.
ПРИМЕЧАНИЕ. Если вы хотите, чтобы на вашей первой странице отображалось последнее сообщение, вам необходимо использовать свойство sort в запросе. См. Мой пример выше, чтобы узнать, как выполнить сортировку с использованием поля frontmatter___date.
Элементы управления разбиением на страницы
Замечательно, что наши сообщения разбиты на несколько страниц. Но если единственный способ перемещаться между ними - это изменить URL-адрес, у нас возникнут проблемы.
Здесь нам поможет добавление элементов управления нумерацией страниц. Мы собираемся добавить пару специальных кнопок, которые позволяют переходить к следующему и предыдущему перемещению по страницам. Мы также добавим список страниц посередине кнопок, чтобы вы могли пропускать страницы, если хотите.
Создание компонента разбивки на страницы
Прежде чем мы сможем реализовать это на нашей странице, нам сначала нужно создать наш Pagination компонент. Теперь посмотрим на код.
export default function Pagination({ pageSize, totalCount, currentPage }) {
const totalPages = Math.ceil(totalCount / pageSize);
const prevPage = currentPage - 1;
const nextPage = currentPage + 1;
const hasNextPage = nextPage <= totalPages;
const hasPrevPage = prevPage >= 1;
const prevLink = prevPage === 1 ? "blog" : `blog/${prevPage}`;
const nextLink = `blog/${nextPage}`;
return (
<div>
<Link title="prev page" disabled={!hasPrevPage} to={prevLink}>
← <span className="word">Previous</span>{" "}
</Link>
{Array.from({ length: totalPages }).map((_, i) => (
<Link
key={`blog-page-${i}`}
className={currentPage === 1 && i === 0 ? "current" : ""}
to={`blog/${i === 0 ? "" : i + 1}`}
>
{i + 1}
</Link>
))}
<Link title="next page" disabled={!hasNextPage} to={nextLink}>
<span className="word">Next</span> →
</Link>
</div>
);
}
Код не слишком сложный, у нас есть пара Link элементов от Гэтсби. Затем еще одно из наших 49_ специальных предложений, сделанных ранее. Однако на этот раз вместо .forEach() мы используем .map(), потому что хотим вернуть элементы.
Давайте разберемся с этим.
Создание ссылок
Первый раздел, на который мы собираемся взглянуть, - это код, который генерирует для нас ссылки на основе пропсов, которые мы передаем. Вот код:
export default function Pagination({
pageSize,
totalCount,
currentPage
}) {
const totalPages = Math.ceil(totalCount / pageSize);
const prevPage = currentPage - 1;
const nextPage = currentPage + 1;
const hasNextPage = nextPage <= totalPages;
const hasPrevPage = prevPage >= 1;
const prevLink = prevPage === 1 ? "blog" : `blog/${prevPage}`;
const nextLink = `blog/${nextPage}`;
// ... Rest of the component here
Итак, что мы здесь делаем?
Сначала мы передаем серию реквизитов:
- pageSize: количество сообщений на каждой странице.
- totalCount: общее количество сообщений в блоге по запросу GraphQL на странице блога.
- currentPage: это происходит из контекста, который мы добавили в
gatsby-node.js. Он деструктурируется на странице и затем передается компоненту.
После этого мы создаем серию переменных, которые используются, чтобы определить, есть ли другая страница для перехода. И если да, то каков URL?
- totalPages: Int: Общее количество требуемых страниц.
- prevPage: Int: определяет индекс предыдущей страницы на основе текущей.
- nextPage: Int: определяет индекс следующей страницы на основе текущей.
- hasNextPage: Bool: Проверяет, меньше ли
nextPageили равноtotalPages. - hasPrevPage: Bool: Проверяет, больше ли переменная
prevPageили равна единице.
Эти 5 переменных используются по всему компоненту, чтобы решить, следует ли отображать элементы. Но мы вернемся к этому через секунду. Во-первых, нам нужно создать следующую и предыдущую ссылки, которые являются нашими последними двумя переменными.
- prevLink: Str: Проверяет, равна ли переменная
prevPageединице. В таком случае установите для переменной значение'blog', которое перенаправит вас на главную страницу блога. В противном случае установите для переменной значениеblog/${prevPage}. - nextLink: Str: установлено значение
blog/${nextPage}. Это сделано потому, что у нас есть отдельная переменная, контролирующая, есть ли другая страница или нет.
Теперь мы рассмотрели все переменные, необходимые для создания элементов, давайте посмотрим на создание кнопок.
Кнопки "Далее" и "Назад"
Код для предыдущей и следующей кнопок на самом деле похож, с небольшими изменениями слов. По этой причине я собираюсь разбить только одну из них, чтобы мы могли понять, как они работают. Сначала давайте посмотрим на полный код, чтобы увидеть различия:
<Link title="prev page" disabled={!hasPrevPage} to={prevLink}>
← <span className="word">Previous</span>{' '}
</Link>
<Link title="next page" disabled={!hasNextPage} to={nextLink}>
<span className="word">Next</span> →
</Link>
Структура ссылок представляет собой элемент Gatsby Link, оборачивающий span, описывающий, что делает кнопка. Давайте посмотрим, что мы с ними делаем:
- title: Str: Мы устанавливаем атрибут title для элемента, чтобы объявлять пользователю, что делает каждая ссылка.
- disabled: Bool: Здесь используются две переменные
hasPrevPageиhasNextPage. Если переменная говорит, что следующая или предыдущая страница находится за пределами доступных страниц, она отключит ссылку. Затем это стилизуется с помощью CSS, чтобы уменьшить непрозрачность и предотвратить нажатие на них пользователем. Проверьте этот код ниже. - to: Str: это пункт назначения, к которому мы хотим, чтобы элемент переместился при нажатии.
Это касается функциональности, последняя часть - добавление текстовых элементов, чтобы пометить их на экране. Для этого мы используем span, оборачивающий соответствующее слово и следующую / предыдущую стрелку в зависимости от кнопки.
Код CSS для отключения ссылки:
&[disabled] {
pointer-events: none;
text-decoration: line-through;
color: var(--black);
opacity: 0.5;
}
Добавление всех страниц
Мы почти закончили работу с компонентом разбивки на страницы. Нам просто нужно добавить ссылки для каждой страницы между предыдущей и следующей кнопками.
Вот код для добавления ссылок на страницы:
{
Array.from({ length: totalPages }).map((_, i) => (
<Link
key={`blog-page-${i}`}
className={currentPage === 1 && i === 0 ? "current" : ""}
to={`blog/${i === 0 ? "" : i + 1}`}
>
{i + 1}
</Link>
));
}
Он основан на принципе, аналогичном тому, который мы использовали в прошлом для создания каждой страницы в gatsby-node.js. Однако вместо того, чтобы использовать .forEach() для цикла по каждому индексу, мы используем .map(), чтобы мы могли вернуть элемент Link.
Давайте разберемся, что происходит в этом блоке кода:
- Мы создаем массив с длиной, равной
totalPages, а затем сопоставляем каждый индекс. - Мы создаем элемент
Linkи передаем ему 3 свойства: - key: Str: стандартное ключевое свойство, необходимое React при возврате элементов с карты.
- className: Str: Используется для добавления «текущего» класса к элементу, если мы находимся на этой странице, чтобы разрешить стилизацию.
- to: Str: Пункт назначения, к которому мы хотим перейти по ссылке.
- Наконец, мы добавляем текст внутри
Link, который является индексом плюс 1, чтобы свести на нет 0-индексирование массивов JavaScript.
Вот CSS для текущего стиля, который мы добавили:
&[aria-current],
&.current {
color: var(--green);
font-weight: 600;
border-bottom: 2px solid var(--green);
}
Добавление в файл подкачки
Мы создали компонент нумерации страниц, пора добавить его в файл страницы нашего блога следующим образом:
return (
<>
<Pagination
pageSize={6}
totalCount={totalCount}
currentPage={currentPage || 1}
/>
<AllPostsContainer>
{blogPosts.map((post) => (
<BlogPostCard
key={`blogPostCard-${post.node.frontmatter.id}`}
post={post}
/>
))}
</AllPostsContainer>
<Pagination
pageSize={6}
totalCount={totalCount}
currentPage={currentPage || 1}
/>
</>
);
Поскольку мы разделили весь компонент разбивки на страницы, теперь нужно передать необходимые реквизиты:
- pageSize: Int: Общее количество сообщений на каждой странице.
- totalCount: Int: общее количество сообщений из запроса GraphQL.
- currentPage: Int: индекс текущей страницы, взятый из контекста, если не 1.
Теперь мы должны быть настроены и готовы к рок-н-роллу.
Заключение
Если все пошло по плану, у вас должно получиться что-то похожее по функциональности:

Я не включил CSS в эту статью, кроме одного или двух разделов, чтобы попытаться сократить длину сообщения. Но если вас интересует весь CSS, он доступен на Github для моего сайта.
Одна вещь, которую я не упомянул в этом сообщении, но рекомендую, - это сохранить вашу pageSize переменную в файле .env. Затем вы можете импортировать его в Gatsby, используя parseInt(process.env.GATSBY_PAGE_SIZE)}. Это означает, что если вы когда-нибудь захотите изменить количество сообщений на странице, вам нужно будет изменить его только в одном месте.
Я надеюсь, что вы нашли этот пост полезным, если бы вы это сделали, я был бы очень признателен, если бы вы поделились им с другими в социальных сетях, чтобы они тоже могли извлечь из него пользу. Если у вас есть какие-либо отзывы, я хотел бы их услышать, вы можете связаться со мной в Twitter.
Спасибо за прочтение. 😃
Этот пост изначально был опубликован в моем блоге conermurphy.com. Если вы хотите читать мои сообщения, как только они будут опубликованы, подпишитесь на меня в Twitter.
Больше контента на plainenglish.io