Перейти к содержимому

Создайте страницы тегов

Приготовьтесь…

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

Вы можете динамически создавать целые наборы страниц с помощью файлов .astro, которые экспортируют функцию getStaticPaths().

  1. Создайте новый файл по адресу src/pages/tags/[tag].astro. (Вам придется создать новую папку.) Обратите внимание, что имя файла ([tag].astro) использует квадратные скобки. Вставьте следующий код в файл:

    src/pages/tags/[tag].astro
    ---
    import BaseLayout from '../../layouts/BaseLayout.astro';
    export async function getStaticPaths() {
    return [
    { params: { tag: "astro" } },
    { params: { tag: "успехи" } },
    { params: { tag: "сообщество" } },
    { params: { tag: "ведение блога" } },
    { params: { tag: "неудачи" } },
    { params: { tag: "обучение в открытом доступе" } },
    ];
    }
    const { tag } = Astro.params;
    ---
    <BaseLayout pageTitle={tag}>
    <p>Посты с тегом {tag}</p>
    </BaseLayout>

    Функция getStaticPaths возвращает массив маршрутов страниц, и все страницы по этим маршрутам будут использовать один и тот же шаблон, определённый в файле.

  2. Если вы настроили свои записи блога, замените отдельные значения тегов (например, «astro», «успехи», «сообщество» и т. д.) на теги, используемые в ваших собственных постах.

  3. Убедитесь, что каждая ваша запись содержит хотя бы один тег, записанный в виде массива, например, tags: ["ведение блога"].

  4. Перейдите по адресу http://localhost:4321/tags/astro в предварительном просмотре вашего браузера — вы должны увидеть страницу, созданную динамически из [tag].astro. Проверьте, созданы ли у вас страницы для каждого из ваших тегов по адресам /tags/успехи, /tags/сообщество и /tags/обучение%20в%20открытом%20доступе и т. д., или для каждого из ваших пользовательских тегов. Возможно, вам придется сначала выйти и перезапустить сервер разработки, чтобы увидеть эти новые страницы.

Использование props в динамических маршрутах

Заголовок раздела Использование props в динамических маршрутах
  1. Добавьте следующие пропсы в вашу функцию getStaticPaths(), чтобы сделать данные из всех ваших записей доступными для каждого маршрута страницы.

    Обязательно предоставьте каждому маршруту в вашем массиве новые пропсы, а затем сделайте эти пропсы доступными для вашего шаблона компонента за пределами вашей функции.

    src/pages/tags/[tag].astro
    ---
    import BaseLayout from '../../layouts/BaseLayout.astro';
    export async function getStaticPaths() {
    const allPosts = Object.values(import.meta.glob('../posts/*.md', { eager: true }));
    return [
    { params: { tag: "astro" }, props: {posts: allPosts}},
    { params: { tag: "успехи" }, props: {posts: allPosts}},
    { params: { tag: "сообщество" }, props: {posts: allPosts}},
    { params: { tag: "ведение блога" }, props: {posts: allPosts}},
    { params: { tag: "неудачи" }, props: {posts: allPosts}},
    { params: { tag: "обучение в открытом доступе" }, props: {posts: allPosts}},
    ];
    }
    const { tag } = Astro.params;
    const { posts } = Astro.props;
    ---
  2. Отфильтруйте ваш список постов, чтобы включить только те посты, которые содержат собственный тег страницы.

    /src/pages/tags/[tag].astro
    ---
    const { tag } = Astro.params;
    const { posts } = Astro.props;
    const filteredPosts = posts.filter((post: any) => post.frontmatter.tags?.includes(tag));
    ---
  3. Теперь вы можете обновить ваш HTML-шаблон, чтобы отобразить список записей в блоге, содержащих собственные теги. Добавьте следующий код в [tag].astro:

    src/pages/tags/[tag].astro
    <BaseLayout pageTitle={tag}>
    <p>Посты с тегом {tag}</p>
    <ul>
    {filteredPosts.map((post: any) => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}
    </ul>
    </BaseLayout>
  4. Вы даже можете отрефакторить этот код, чтобы использовать ваш компонент <BlogPost /> вместо элемента списка! (Не забудьте импортировать этот компонент в начале файла [tag].astro.)

    src/pages/tags/[tag].astro
    <BaseLayout pageTitle={tag}>
    <p>Посты с тегом {tag}</p>
    <ul>
    {filteredPosts.map((post: any) => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}
    {filteredPosts.map((post: any) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}
    </ul>
    </BaseLayout>
  5. Проверьте предварительный просмотр в вашем браузере для ваших отдельных страниц с тегами, и теперь вы должны увидеть список всех ваших записей, содержащих этот конкретный тег.

Для каждого из следующих случаев укажите, написан ли код внутри функции getStaticPaths() или вне её.

  1. Вызов import.meta.glob() для получения информации обо всех ваших файлах .md, которую нужно передать каждому маршруту страницы.

  2. Список маршрутов, которые должны быть сгенерированы (возвращены) getStaticPaths()

  3. Полученные значения props и params, которые будут использоваться в HTML-шаблоне.

Продвинутый JavaScript: Генерация страниц из существующих тегов

Заголовок раздела Продвинутый JavaScript: Генерация страниц из существующих тегов

Теперь ваши страницы с тегами статически определены в [tag].astro. Если вы добавите новый тег к сообщению в блоге, вам также придется вернуться на эту страницу и обновить маршруты страниц.

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

  1. Убедитесь, что все ваши записи блога содержат теги

    Пересмотрите каждую из ваших существующих страниц Markdown и убедитесь, что каждая запись содержит массив tags в своих метаданных. Даже если у вас только один тег, он всё равно должен быть записан как массив, например, tags: ["ведение блога"].

  2. Создайте массив со всеми вашими существующими тегами

    Добавьте следующий код, чтобы получить список каждого тега, используемого в ваших блог-постах.

    src/pages/tags/[tag].astro
    ---
    import BaseLayout from '../../layouts/BaseLayout.astro';
    export async function getStaticPaths() {
    const allPosts = Object.values(import.meta.glob('../posts/*.md', { eager: true }));
    const uniqueTags = [...new Set(allPosts.map((post: any) => post.frontmatter.tags).flat())];
    }
    Расскажите мне подробнее, что делает эта строчка кода!

    Всё в порядке, если это не то, что вы бы сами написали!

    Он проходит через каждый пост в Markdown, по одному, и объединяет каждый массив тегов в один большой массив. Затем он создает новый Set из всех найденных индивидуальных тегов (чтобы игнорировать повторяющиеся значения). Наконец, он преобразует этот набор в массив (без дублирования), который вы можете использовать для отображения списка тегов на вашей странице.

    Теперь у вас есть массив uniqueTags с элементами "astro", "successes", "community", "blogging", "setbacks", "learning in public"

  3. Замените значение return функции getStaticPaths

    src/pages/tags/[tag].astro
    return [
    { params: { tag: "astro" }, props: {posts: allPosts}},
    { params: { tag: "успехи" }, props: {posts: allPosts}},
    { params: { tag: "сообщество" }, props: {posts: allPosts}},
    { params: { tag: "ведение блога" }, props: {posts: allPosts}},
    { params: { tag: "неудачи" }, props: {posts: allPosts}},
    { params: { tag: "обучение в открытом доступе" }, props: {posts: allPosts}},
    ];
    return uniqueTags.map((tag) => {
    const filteredPosts = allPosts.filter((post: any) => post.frontmatter.tags.includes(tag));
    return {
    params: { tag },
    props: { posts: filteredPosts },
    };
    });
  4. Функция getStaticPaths всегда должна возвращать список объектов, содержащих params (параметры каждого маршрута страницы) и, возможно, любые props (данные, которые вы хотите передать на эти страницы). Ранее вы определили каждое имя тега, которое использовалось в вашем блоге, и передали весь список постов как свойства на каждую страницу.

    Теперь вы генерируете этот список объектов автоматически, используя ваш массив uniqueTags для определения каждого параметра.

    И теперь список всех записей блога фильтруется до его отправки на каждую страницу в качестве свойств. Обязательно удалите предыдущую строку кода, фильтрующую посты, и обновите ваш HTML-шаблон, чтобы использовать posts вместо filteredPosts.

    src/pages/tags/[tag].astro
    const { tag } = Astro.params;
    const { posts } = Astro.props;
    const filteredPosts = posts.filter((post) => post.frontmatter.tags.includes(tag));
    ---
    <!-- -->
    <ul>
    {filteredPosts.map((post: any) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}
    {posts.map((post: any) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}
    </ul>

Чтобы проверить свою работу, или если вы просто хотите скопировать полный, правильный код в [tag].astro, то вот как должен выглядеть ваш компонент Astro:

src/pages/tags/[tag].astro
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import BlogPost from '../../components/BlogPost.astro'
export async function getStaticPaths() {
const allPosts = Object.values(import.meta.glob('../posts/*.md', { eager: true }));
const uniqueTags = [...new Set(allPosts.map((post: any) => post.frontmatter.tags).flat())];
return uniqueTags.map((tag) => {
const filteredPosts = allPosts.filter((post: any) => post.frontmatter.tags.includes(tag));
return {
params: { tag },
props: { posts: filteredPosts },
};
});
}
const { tag } = Astro.params;
const { posts } = Astro.props;
---
<BaseLayout pageTitle={tag}>
<p>Посты с тегом {tag}</p>
<ul>
{posts.map((post: any) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}
</ul>
</BaseLayout>

Теперь вы должны быть в состоянии посетить любую из ваших страниц с тегами в предварительном просмотре браузера.

Перейдите по адресу http://localhost:4321/tags/сообщество и вы должны увидеть список ваших записей с тегом сообщество. Аналогично, переход по адресу http://localhost:4321/tags/обучение%20в%20открытом%20доступе должен отображать список записей с тегом обучение в открытом доступе.

В следующем разделе вы создадите навигационные ссылки на эти страницы.

Выберите термин, который соответствует описанию.

  1. Функция, которая возвращает массив маршрутов страниц.

  2. Процесс создания нескольких маршрутов страниц из одного файла в Astro.

  3. Значение, которое определяет имя маршрута страницы, генерируемого динамически.

Внести свой вклад Сообщество Sponsor