Модуль @nuxt/content в Nuxt
Модуль @nuxt/content предоставляет мощный способ работы с файлами контента (такими как Markdown, YAML, JSON, CSV и др.) в вашем Nuxt приложении. Он позволяет вам писать контент в простых форматах и затем легко отображать его на вашем сайте, используя Vue-компоненты.
Установка
Для начала установите модуль @nuxt/content:
npm install --save-dev @nuxt/content
# или
yarn add -D @nuxt/contentЗатем добавьте @nuxt/content в секцию modules вашего файла nuxt.config.js:
export default {
modules: [
'@nuxt/content'
],
// ... другие настройки
}Структура каталога content/
После установки модуля в корне вашего проекта будет создан каталог content/. Именно здесь вы будете размещать ваши файлы контента. Структура подкаталогов внутри content/ будет определять структуру URL-маршрутов для вашего контента (если вы используете динамические маршруты @nuxt/content).
Пример структуры:
content/
├── index.md
├── about.md
├── blog/
│ ├── first-post.md
│ └── second-post.md
└── authors/
├── john-doe.json
└── jane-doe.yamlНа основе этой структуры @nuxt/content автоматически создаст следующие маршруты (если вы используете <nuxt-content> или $content):
/(изcontent/index.md)/about(изcontent/about.md)/blog/first-post(изcontent/blog/first-post.md)/blog/second-post(изcontent/blog/second-post.md)/authors/john-doe(изcontent/authors/john-doe.json)/authors/jane-doe(изcontent/authors/jane-doe.yaml)
Использование <nuxt-content>
Компонент <nuxt-content> используется для отображения обработанного контента внутри ваших Vue-шаблонов. Он принимает проп document, который является результатом запроса к вашему контенту.
Пример отображения контента из content/index.md (pages/index.vue):
<template>
<div>
<nuxt-content :document="page" />
</div>
</template>
<script setup>
const { data: page } = await useAsyncData('index', () => queryContent('index').findOne());
</script>Здесь queryContent('index').findOne() запрашивает файл контента index (без расширения) из каталога content/ и возвращает его содержимое в объекте page. Компонент <nuxt-content :document="page" /> затем отображает обработанный HTML-контент.
Использование $content
Вы также можете получить доступ к контенту программно, используя инжектированный объект $content.
Пример получения списка всех постов блога (pages/blog/index.vue):
<template>
<div>
<h1>Блог</h1>
<ul>
<li v-for="post in posts" :key="post.slug">
<nuxt-link :to="`/blog/${post.slug}`">{{ post.title }}</nuxt-link>
</li>
</ul>
</div>
</template>
<script setup>
const { data: posts } = await useAsyncData('posts', () => queryContent('blog').find());
</script>Здесь queryContent('blog').find() запрашивает все файлы контента, находящиеся в подкаталоге content/blog/, и возвращает массив объектов, каждый из которых представляет пост. Каждый пост имеет свойство slug, которое генерируется на основе имени файла.
Запросы к контенту (queryContent)
Функция queryContent() является основным способом взаимодействия с вашим контентом. Она возвращает объект запроса, который позволяет вам применять различные фильтры, сортировки и выборки к вашему контенту.
Примеры запросов:
Получить один документ по пути:
javascriptqueryContent('about').findOne() // content/about.md queryContent('blog/first-post').findOne() // content/blog/first-post.mdПолучить все документы в каталоге:
javascriptqueryContent('blog').find() // Все файлы в content/blog/Фильтрация по свойствам (Frontmatter): Предположим, ваши Markdown файлы имеют Frontmatter с полем
category:markdown--- title: Мой первый пост category: новости --- Содержимое поста...javascriptqueryContent('blog').where({ category: 'новости' }).find() // Получить все посты из категории "новости" queryContent('blog').where({ category: { $ne: 'новости' } }).find() // Получить все посты, кроме "новости" queryContent('blog').where({ tags: { $contains: 'vue' } }).find() // Получить все посты, содержащие тег "vue"Сортировка:
javascriptqueryContent('blog').sortBy('date', 'desc').find() // Получить все посты, отсортированные по дате (сначала новые) queryContent('blog').sortBy('title', 'asc').find() // Получить все посты, отсортированные по заголовку по возрастаниюВыборка полей:
javascriptqueryContent('blog').select(['title', 'slug', 'date']).find() // Получить только заголовок, slug и датуОграничение количества результатов:
javascriptqueryContent('blog').limit(5).find() // Получить только первые 5 постовПропуск результатов:
javascriptqueryContent('blog').skip(5).limit(5).find() // Получить следующие 5 постов (для пагинации)
Frontmatter
Markdown и YAML файлы могут содержать Frontmatter - метаданные, заключенные между --- в начале файла. @nuxt/content автоматически парсит Frontmatter и делает его доступным в объекте документа.
Пример Markdown с Frontmatter:
---
title: Заголовок моего поста
date: 2023-10-27
tags: ['nuxt', 'javascript']
---
Основное содержимое поста...В вашем Vue-компоненте вы сможете получить доступ к этим данным так:
<template>
<div>
<h1>{{ post.title }}</h1>
<p>Опубликовано: {{ post.date }}</p>
<ul>
<li v-for="tag in post.tags" :key="tag">{{ tag }}</li>
</ul>
<nuxt-content :document="post" />
</div>
</template>
<script setup>
const route = useRoute();
const { data: post } = await useAsyncData(`post-${route.params.slug}`, () =>
queryContent('blog', route.params.slug).findOne()
);
</script>Компоненты для отображения контента
Модуль @nuxt/content предоставляет несколько полезных компонентов для отображения вашего контента:
<nuxt-content :document="doc" />: Отображает основной обработанный контент документа.<ContentRenderer :value="doc" />: Более низкоуровневый компонент для рендеринга контента.<ContentRendererMarkdown :value="markdownString" />: Рендерит строку Markdown.<ContentRendererHtml :value="htmlString" />: Рендерит строку HTML.
Конфигурация модуля
Вы можете настроить модуль @nuxt/content в секции content вашего файла nuxt.config.js.
Пример конфигурации:
export default {
modules: [
'@nuxt/content'
],
content: {
// Настройки модуля
markdown: {
remarkPlugins: [
'remark-emoji' // Пример плагина Remark для обработки эмодзи
],
rehypePlugins: [
'rehype-katex' // Пример плагина Rehype для обработки LaTeX
]
},
yaml: {
// Настройки для YAML
},
csv: {
// Настройки для CSV
delimiters: {
delimiter: ';'
}
},
liveEdit: false // Отключить режим "живого редактирования" (для разработки)
},
// ... другие настройки
}Кастомные компоненты для рендеринга
Вы можете зарегистрировать кастомные Vue-компоненты для рендеринга определенных элементов Markdown (например, <h2>, <code>). Создайте каталог components/content/ и поместите туда ваши компоненты (например, components/content/H2.vue, components/content/CodeInline.vue). @nuxt/content автоматически их подхватит.
Режим разработки (liveEdit)
В режиме разработки (liveEdit: true), @nuxt/content отслеживает изменения в ваших файлах контента и автоматически обновляет страницу при их сохранении. Это значительно упрощает процесс разработки контент-ориентированных сайтов.
Заключение
Модуль @nuxt/content предоставляет удобный и мощный способ интеграции контента в ваше Nuxt приложение. Благодаря простой структуре каталогов, мощным возможностям запросов и удобным компонентам, вы можете легко создавать блоги, документации, портфолио и другие контент-ориентированные сайты.