您正在阅读 Nuxt 内容 V1 文档。阅读最新版本
代码片段
用法
asyncData
export default {
async asyncData({ $content, params }) {
const article = await $content('articles', params.slug).fetch()
return {
article
}
}
}
head
根据在 前置信息 中定义的标题和描述添加动态元数据
export default {
async asyncData({ $content, params }) {
const article = await $content('articles', params.slug).fetch()
return {
article
}
},
head() {
return {
title: this.article.title,
meta: [
{ hid: 'description', name: 'description', content: this.article.description },
// Open Graph
{ hid: 'og:title', property: 'og:title', content: this.article.title },
{ hid: 'og:description', property: 'og:description', content: this.article.description },
// Twitter Card
{ hid: 'twitter:title', name: 'twitter:title', content: this.article.title },
{ hid: 'twitter:description', name: 'twitter:description', content: this.article.description }
]
}
}
}
功能
搜索
通过使用 watch 添加搜索输入组件
<template>
<div>
<input v-model="query" type="search" autocomplete="off" />
<ul v-if="articles.length">
<li v-for="article of articles" :key="article.slug">
<NuxtLink :to="{ name: 'blog-slug', params: { slug: article.slug } }">{{ article.title }}</NuxtLink>
</li>
</ul>
</div>
</template>
<script>
export default {
data () {
return {
query: '',
articles: []
}
},
watch: {
async query (query) {
if (!query) {
this.articles = []
return
}
this.articles = await this.$content('articles')
.only(['title', 'slug'])
.sortBy('createdAt', 'asc')
.limit(12)
.search(query)
.fetch()
}
}
}
</script>
查看 搜索文档
上一页和下一页
使用 surround
方法添加上一页和下一页链接
<template>
<div>
<NuxtLink v-if="prev" :to="{ name: 'blog-slug', params: { slug: prev.slug } }">
{{ prev.title }}
</NuxtLink>
<NuxtLink v-if="next" :to="{ name: 'blog-slug', params: { slug: next.slug } }">
{{ next.title }}
</NuxtLink>
</div>
</template>
<script>
export default {
async asyncData({ $content, params }) {
const [prev, next] = await $content('articles')
.only(['title', 'slug'])
.sortBy('createdAt', 'asc')
.surround(params.slug)
.fetch()
return {
prev,
next
}
}
}
</script>
如果多个文档具有相同的 slug,则应将 path
作为 surround
方法的第一个参数,而不是 slug
。 这是因为 Nuxt 内容根据第一个匹配的文档查找上一页和下一页文档。
例如,如果您按 position
对文档进行排序,即使当前页面显示的是较高位置的文档,也将始终使用位置较低的文档进行计算。
查看 surround 文档
不区分大小写的排序
需要解决 Nuxt 内容的不区分大小写排序问题,为文档添加额外的属性,其值是小写的。
export default {
hooks: {
'content:file:beforeInsert': (document) => {
if (document.extension === '.md') {
Object.entries(document).forEach(([key, value]) => {
const _key = `case_insensitive__${key}`; // prefix is arbitrary
if (!document[_key] && typeof value === 'string') {
document[_key] = value.toLocaleLowerCase();
}
});
}
}
}
};
然后,使用要排序的额外属性的键调用 sortBy
方法。
export default {
async asyncData({ $content, params }) {
const articles = await $content('articles', params.slug)
.sortBy('case_insensitive__title', 'asc') // Set prefixed prop
.fetch()
return {
articles
}
}
}
查看
sortBy
文档
目录
通过循环遍历 toc 数组并使用 id
链接到它以及使用 text
显示标题来添加目录。 我们可以使用 depth
以不同的方式设置标题的样式
<template>
<ul>
<li
v-for="link of article.toc"
:key="link.id"
:class="{ 'toc2': link.depth === 2, 'toc3': link.depth === 3 }"
>
<NuxtLink :to="`#${link.id}`">{{ link.text }}</NuxtLink>
</li>
</ul>
</template>
<script>
export default {
async asyncData({ $content, params }) {
const article = await $content('articles', params.slug)
.fetch()
return {
article
}
}
}
</script>
查看 目录文档
动态路由
假设您要创建一个应用程序,其路由遵循 content/
文件结构。 您可以通过创建一个 pages/_.vue
组件来做到这一点
<script>
export default {
async asyncData ({ $content, app, params, error }) {
const path = `/${params.pathMatch || 'index'}`
const [article] = await $content({ deep: true }).where({ path }).fetch()
if (!article) {
return error({ statusCode: 404, message: 'Article not found' })
}
return {
article
}
}
}
</script>
这样,如果您访问 /themes/docs
路由,它将显示 content/themes/docs.md
文件。 如果您需要为目录创建索引页面,则需要创建一个与目录同名的文件
content/
themes/
docs.md
themes.md
如果您使用 nuxt-i18n
,请不要忘记在调用之前加上当前语言环境前缀。
自定义高亮显示
Highlight.js
import highlightjs from 'highlight.js'
const wrap = (code, lang) => `<pre><code class="hljs ${lang}">${code}</code></pre>`
export default {
// Complete themes: https://github.com/highlightjs/highlight.js/tree/main/src/styles
css: ['highlight.js/styles/nord.css'],
modules: ['@nuxt/content'],
content: {
markdown: {
highlighter(rawCode, lang) {
if (!lang) {
return wrap(highlightjs.highlightAuto(rawCode).value, lang)
}
return wrap(highlightjs.highlight(rawCode, { language: lang }).value, lang)
}
}
}
}
Shiki
Shiki 是一个语法高亮器,它使用 TexMate 语法,并使用 VS Code 主题对标记进行着色。 它将生成与 VS Code 中的代码完全一致的 HTML。
您无需添加自定义样式,因为 Shiki 会将其内联到 HTML 中。
import shiki from 'shiki'
export default {
modules: ['@nuxt/content'],
content: {
markdown: {
async highlighter() {
const highlighter = await shiki.getHighlighter({
// Complete themes: https://github.com/shikijs/shiki/tree/main/packages/shiki/themes
theme: 'nord'
})
return (rawCode, lang) => {
return highlighter.codeToHtml(rawCode, lang)
}
}
}
}
}
Shiki Twoslash
Twoslash 是一种用于 TypeScript 代码的标记格式。 在内部,Twoslash 使用 TypeScript 编译器生成丰富的高亮信息。
要更好地了解 Twoslash 的工作原理,您可以访问 官方 TypeScript 文档 并将鼠标悬停在其中的一些代码示例上。
您可以使用 Shiki Twoslash 达到相同的结果。 此包也是为官方 TypeScript 文档提供支持的包。
import {
createShikiHighlighter,
runTwoSlash,
renderCodeToHTML
} from 'shiki-twoslash'
export default {
modules: ['@nuxt/content'],
content: {
markdown: {
async highlighter() {
const highlighter = await createShikiHighlighter({
// Complete themes: https://github.com/shikijs/shiki/tree/main/packages/shiki/themes
theme: 'nord'
})
return (rawCode, lang) => {
const twoslashResults = runTwoSlash(rawCode, lang)
return renderCodeToHTML(
twoslashResults.code,
lang,
['twoslash'],
{},
highlighter,
twoslashResults
)
}
}
}
}
}
Remark 插件
Nuxt 内容在幕后使用 remark 来处理 markdown 文档。 创建 remark 插件是操作文档并添加新功能的一种方式。
列出所有贡献者
假设您要在一个文档中列出项目的贡献者。 您可以创建一个插件,该插件获取所有贡献者并将它们注入到文档数据中。
- 创建插件。 如果
fetchContributors
设置为true
,则此插件将获取贡献者
const fetch = require('node-fetch')
module.exports = function () {
return async (tree, { data }) => {
if (data.fetchContributors) {
const contributors = await fetch(
'https://api.github.com/repos/nuxt/content/contributors'
).then(res => res.json())
.then(res => res.map(({ login }) => login))
data.$contributors = [...new Set(contributors)]
}
return tree
}
}
- 在 Nuxt 配置中注册插件
export default {
contents: {
markdown: {
remarkPlugins: [
'~~/plugins/contributors.js'
]
}
}
}
- 创建一个简单的组件来显示贡献者
<template>
<ul>
<li v-for="(item, i) in items" :key="i">
{{ item }}
</li>
</ul>
</template>
<script>
export default {
props: {
items: {
type: Array,
default: () => []
}
}
}
- 最后,使用这些组件并标记文档以获取贡献者
---
title: Nuxt Content
fetchContributors: true
---
## Contributors
<list :items="$contributors"></list>