Markdown
用法
定义一个集合
import { defineCollection, defineContentConfig, z } from '@nuxt/content'
export default defineContentConfig({
collections: {
blog: defineCollection({
type: 'page',
source: 'blog/*.md',
schema: z.object({
date: z.string()
})
})
}
})
创建 .md 文件
在 content/blog/ 目录下创建博客文章。
---
date: 2020-11-11
---
# Foo
This is Foo blog post.
---
date: 2024-12-12
---
Hello
I am bar. Nice to meet you.
查询 Markdown 文件
现在我们可以查询博客文章了:
// Get the foo post
const fooPost = await queryCollection('blog').path('/foo').first()
// Find all posts
const allPosts = await queryCollection('blog').order('date', 'DESC').all()
显示 Markdown
要显示 Markdown 文件的内容,你可以使用 <ContentRenderer> 组件。
<script setup>
const slug = useRoute().params.slug
const { data: post } = await useAsyncData(`blog-${slug}`, () => {
return queryCollection('blog').path(`/blog/${slug}`).first()
})
</script>
<template>
<!-- Render the blog post as Prose & Vue components -->
<ContentRenderer :value="post" />
</template>
<ContentRenderer> 组件和 Prose Components 的信息。Frontmatter
Frontmatter 是基于 Markdown 的 CMS 的一种约定,用于为页面提供元数据,如描述或标题。在 Nuxt Content 中,frontmatter 使用 YAML 语法,采用 key: value 键值对的形式。
这些数据在渲染内容时可用,并且可以存储你需要的任何信息。
语法
你可以在 content/ 目录下的 Markdown 文件顶部使用 --- 标识符声明一个 frontmatter 块。
---
title: 'Title of the page'
description: 'meta description of the page'
---
<!-- Content of the page -->
const home = await queryCollection('content').path('/').first()
console.log(home.title)
// => 'Title of the page'
console.log(home.description)
// => 'meta description of the page'
console.log(home.body)
// => AST object of the page content
原生参数
| 键 | 类型 | 默认值 | 描述 |
title | string | 页面的第一个 <h1> | 页面标题,也会被注入到 meta 标签中。 |
description | string | 页面的第一个 <p> | 页面描述,将显示在标题下方并注入到 meta 标签中。 |
navigation | boolean | true | 定义该页面是否包含在 queryCollectionNavigation 的返回值中。 |
MDC 语法
我们创建了 MDC 语法来增强 Markdown,并使你能够在 Markdown 中集成带有插槽和 props 的 Vue 组件。
Vue 组件
你可以在你的 Markdown 文件中使用任何 Vue 组件。
我们提供了一种特殊的语法,使在 Markdown 文件中使用组件更加容易。
::component-name
Default slot content
::
全局注册:如果你不使用
components/content/ 目录,则在 Markdown 中使用的组件必须在你的 Nuxt 应用程序中标记为 global,请访问 Nuxt 3 文档 了解更多信息。块级组件
块级组件是接受 Markdown 内容或其他组件作为插槽的组件。
该组件必须包含至少一个 <slot /> 组件才能接受格式化文本。
在 Markdown 文件中,使用 :: 标识符来使用该组件。
::card
The content of the card
::
<!-- components/content/Card.vue -->
<template>
<div class="p-2 border bg-white dark:bg-black dark:border-gray-700 rounded">
<slot />
</div>
</template>
The content of the card
插槽
组件的插槽可以接受内容或其他组件。
- 默认插槽 渲染块级组件内部的顶层内容或使用
#default - 具名插槽 使用
#标识符渲染相应的内容。
::hero
My Page Title
#description
This will be rendered inside the `description` slot.
::
<template>
<section>
<h1 class="text-4xl">
<slot mdc-unwrap="p" />
</h1>
<slot name="description" />
</section>
</template>
My Page Title
<slot /> 组件的信息。::my-title
A [rich text](/) will be **rendered** by the component.
::
<template>
<h1 class="text-4xl">
<slot mdc-unwrap="p" />
</h1>
</template>
A rich text will be rendered by the component.
Props
有两种方法可以使用 MDC 将 props 传递给组件。
内联方法
{} 标识符通过使用 key=value 语法以简洁的方式将 props 传递给组件。
::alert{type="warning"}
The **alert** component.
::
<script setup>
defineProps(['type'])
</script>
<template>
<div :class="[type]">
<slot mdc-unwrap="p" />
</div>
</template>
The alert component.
:class="type" 与 :class="[type]" 的区别::class="type"- 当 type 是字符串时,直接应用对应的类名
- 当 type 是数组时,Vue 会将数组直接转换为字符串(可能导致意外的 class1,class2 结果)
- 当 type 是对象时,Vue 会将其视为类名映射对象
:class="[type]"- 明确指示 Vue 使用数组语法
- 正确处理数组中的类名(自动展开)
- 可以与其他类名组合:
:class="['static-class', type]" - 提供更好的类型提示
[type] 是动态 class 绑定的数组语法。多个 props 可以用空格分隔:
::alert{type="warning" icon="exclamation-circle"}
Oops! An error occurred
::
v-bind 简写 : 也可以用于将 prop 绑定到 frontmatter 中的一个值。
---
type: "warning"
---
::alert{:type="type"}
Your warning
::
如果你想将数组或对象作为 props 传递给组件,你可以将它们作为 JSON 字符串传递,并在 prop 键前加上冒号以自动解码 JSON 字符串。请注意,在这种情况下,你应该为值字符串使用单引号,以便可以使用双引号传递有效的 JSON 字符串:
::dropdown{:items='["Nuxt", "Vue", "React"]'}
::
::dropdown{:items='[1,2,3.5]'}
::
::chart{:options='{"responsive": true, "scales": {"y": {"beginAtZero": true}}}'}
::
::CardGroup{:ui='{"base":"sm:grid-cols-3"}' :highlight="true" :ids='[101,102,103]'}
:::Card{title="Solo" :tags='["个人","独立开发"]'}
Tailored for indie hackers, freelancers and solo founders.
:::
:::Card{title="Startup" :tags='["小团队","创业"]'}
Best suited for small teams, startups and agencies with up to 5 developers.
:::
:::Card{title="Organization" :tags='["企业","大团队"]'}
Ideal for larger teams and organizations with up to 20 developers.
:::
::
YAML 方法
YAML 方法使用 --- 标识符每行声明一个 prop,这对于提高可读性很有用。
::icon-card
---
icon: IconNuxt
description: Harness the full power of Nuxt and the Nuxt ecosystem.
title: Nuxt Architecture.
---
::
<script setup>
defineProps({
title: {
type: String,
default: 'Default title'
},
description: {
type: String,
default: 'Default description'
},
icon: {
type: String,
default: 'IconMarkdown'
}
})
</script>
<template>
<div class="p-6 border bg-white dark:bg-black dark:border-gray-700 rounded">
<component :is="icon" class="w-20 h-20" />
<h2 class="text-3xl font-semibold mb-2">
{{ title }}
</h2>
<p>{{ description }}</p>
</div>
</template>
属性
属性对于高亮和修改段落的一部分很有用。其语法几乎与内联组件和 Markdown 链接语法类似。
可能的值是所有具名属性、带有 .class-name 标记的类以及带有 #id-name 的 ID。
Hello [World]{style="color: green;" .custom-class #custom-id}!
Hello World !
除了 mdc 组件和 span 之外,属性语法还适用于图像、链接、内联 code、*粗体* 和 _斜体_ 文本。
Attributes work on:
- [link](#attributes){style="background-color: pink;"}, `code`{style="color: cyan;"},
- _italic_{style="background-color: yellow; color:black;"} and **bold**{style="background-color: lightgreen;"} texts.
Attributes work on:
- link,
code, - italic and bold texts.
在 Markdown 中绑定数据
你可以使用 {{ $doc.variable || 'defaultValue' }} 语法在你的 Markdown 文档中绑定数据。这些值可以在文档顶部的 YAML frontmatter 中定义,也可以在每个 MDC 组件中定义,或者使用 <ContentRenderer> 组件的 data prop 注入。
在 YAML 中定义
---
title: 'Title of the page'
description: 'meta description of the page'
customVariable: 'Custom Value'
---
# The Title is {{ $doc.title }} and customVariable is {{ $doc.customVariable || 'defaultValue' }}
使用 <ContentRenderer> 从外部定义
<template>
<div>
<ContentRenderer :value="data" :data="mdcVars"/>
<button type="button" v-on:click="mdcVars.name = 'Hugo'">Change name</button>
</div>
</template>
<script setup lang="ts">
const { data } = await useAsyncData(() => queryCollection('content').path('/test').first());
const mdcVars = ref({ name: 'Maxime'});
</script>
# Hello {{ $doc.name || 'World' }}
Prose 组件
在 Nuxt Content 中,prose 表示由 Markdown 语法生成的 HTML 标签,例如标题级别和链接。
对于每个 HTML 标签,都会使用一个 Vue 组件,如果需要,你可以覆盖它们,例如 <p> 变为 <ProseP>。
如果你想自定义一个 Prose 组件,以下是推荐步骤:
- 查看原始 组件源码。
- 使用完全相同的 props。
- 在你的
components/content/目录中,给它相同的名称。 - 尽情发挥你的创意 🚀。
代码高亮
Nuxt Content 使用 Shiki,它使用 VSCode 主题为 tokens 着色。
代码块的每一行都在 line 属性中获取其行号,因此可以标记或单独设置行的样式。
图片
你可以将图片添加到你的 public 目录:
content/
01.backface-visibility.md.filter.md
public/
image.png
nuxt.config.ts
package.json
然后像这样在 content 目录下的 Markdown 文件中使用它们:

摘要
可以使用 <!--more--> 作为分隔符从内容中提取内容摘要或总结。
---
title: Introduction
---
Learn how to use `@nuxt/content`.
<!--more-->
Full amount of content beyond the more divider.
除非在 frontmatter props 中定义,否则 description 属性将包含摘要内容。
如果文本中没有 <!--more--> 分隔符,则摘要未定义。
excerpt 字段。const content = defineCollection({
type: 'page',
source: '**',
schema: z.object({
excerpt: z.object({
type: z.string(),
children: z.any(),
}),
}),
})
示例,变量将被注入到文档中:
{
"excerpt": Object
"body": Object
// ... other keys
}