sidebarDepth: 3

在 Markdown 中使用 Vue {#using-vue-in-markdown}

在 VitePress 中,每个 markdown 文件都被编译成 HTML,然后作为 Vue 的单文件组件。这意味着你可以在 markdown 中使用任何 Vue 的功能,包含动态模板、Vue 组件,或者编写在 Vue 页面中通过 <script> 包裹的逻辑中。

对于 VitePress 使用 Vue 3 的编译器来字典检测和优化纯静态部分非常重要。从 JavaScript 负载中剔除被优化的静态内容并加入到占位节点中,它们可以在客户端合成。简而言之,你只需要为页面上的动态内容负责。

模板 {#templating}

插值 {#interpolation}

每个 Markdown 文件首先被编译成 HTML,然后作为 Vue 组件传递到 Vite 处理流程中。这意味着你可以在文本中使用 Vue 风格的插值:

输入

  1. {{ 1 + 1 }}

输出

  1. {{ 1 + 1 }}

指令 {#directives}

指令也起作用:

输入

  1. <span v-for="i in 3">{{ i }} </span>

输出

  1. {{ i }}

访问网站和页面数据 {#access-to-site-page-data}

你可以在 <script> 块中使用 useData并暴露给页面。

输入

  1. <script setup>
  2. import { useData } from 'vitepress'
  3. const { page } = useData()
  4. </script>
  5. <pre>{{ page }}</pre>

输出

  1. {
  2. "path": "/using-vue.html",
  3. "title": "Using Vue in Markdown",
  4. "frontmatter": {}
  5. }

Escaping {#escaping}

默认情况下,::: 代码块会自动使用 v-pre 包装,要在内联代码片段或纯文本中显示原生的双大括号或特定的 Vue 语法,需要使用 v-pre 自定义容器对段落进行换行:

输入

  1. ::: v-pre
  2. `{{ This will be displayed as-is }}`
  3. :::

输出

::: v-pre {{ This will be displayed as-is }} :::

使用组件 {#using-components}

当你需要更加灵活时,VitePress 允许你使用自己的 Vue 组件扩展你的创作工具箱。

在 markdown 中导入组件 {#importing-components-in-markdown}

如果你的组件将只在少数几个地方使用,那么推荐的使用方法是在使用它的文件中导入组件。

  1. <script setup>
  2. import CustomComponent from '../components/CustomComponent.vue'
  3. </script>
  4. # Docs
  5. This is a .md using a custom component
  6. <CustomComponent />
  7. ## More docs
  8. ...

在主题中注册全局组件 {#registering-global-components-in-the-theme}

如果这些组件将在文档中的多个页面中使用,它们可以在主题中全局注册(或者作为扩展默认 VitePress 主题的一部分)。详情请查看主题定制指南

.vitepress/Theme/index.js 文件中,enhanceApp 函数接收 Vue 应用实例,因此你可以像在常规 Vue 应用中一样注册组件

  1. import DefaultTheme from 'vitepress/theme'
  2. export default {
  3. ...DefaultTheme,
  4. enhanceApp({ app }) {
  5. app.component('VueClickAwayExample', VueClickAwayExample)
  6. }
  7. }

稍后在你的 markdown 文件中,该组件可以在内容之间交错使用。

  1. # Vue Click Away
  2. <VueClickAwayExample />

::: warning IMPORTANT 确保自定义组件的名称包含连字符或采用 PascalCase 格式。否则会被当作内联元素包装在一个 p 标签中,因为 p 不允许在里面放置内联元素,所以会导致 hydration 不匹配。 :::

在 headers 中使用组件 {#using-components-in-headers}

你可以在标题中使用 Vue 组件,但请注意以下语法之间的区别:

Markdown Output HTML Parsed Header
  1. # text <Tag/>
<h1>text <Tag/></h1> text
  1. # text `<Tag/>`
<h1>text <code>&lt;Tag/&gt;</code></h1> text <Tag/>

code 包装的 HTML 将按原样显示,只有没有包装的 HTML 才会被 Vue 解析。

::: tip 输出的 HTML 由 markdown-it 完成,而解析的 headers 由 VitePress 处理(同时用于侧栏和文档标题)。 :::

使用 CSS 预处理器 {#using-css-pre-processors}

VitePress 对 CSS 预处理器有内置支持: .scss.sass.less.styl.stylus 文件,不需要为它们安装特定于 Vite 的插件,但必须安装相应的预处理器:

  1. # .scss and .sass
  2. npm install -D sass
  3. # .less
  4. npm install -D less
  5. # .styl and .stylus
  6. npm install -D stylus

然后你可以在 Markdown 和主题组件中这样使用:

  1. <style lang="sass">
  2. .title
  3. font-size: 20px
  4. </style>

Script & Style Hoisting {#using-vue-in-markdown-1}

有时你可能只需要对当前页面应用一些 JavaScript 或 CSS,在这些情况下, 你可以直接在 Markdown 文件中编写根级别的 scriptstyle 块,这些会在编译后的 HTML 中 hoisting,并作为生成的 Vue 单文件组件的 scriptstyle 块使用:

内置组件 {#built-in-components}

VitePress 提供了 ClientOnlyOutbound Link 等内置 Vue 组件,详情请查看 全局组件指南

另请参阅:

Browser API 访问限制 {#browser-api-access-restrictions}

因为在生成静态构建时,VitePress 应用程序是在 Node.js 中服务器渲染的,所以任何 Vue 的使用都必须符合 通用代码要求。简而言之,确保只在 beforeMountmounted 钩子中访问 Browser / DOM APIs。

如果你使用或演示的组件是不友好的 SSR (例如,包含自定义指令),可以将它们包装在 ClientOnly 组件中。

  1. <ClientOnly>
  2. <NonSSRFriendlyComponent/>
  3. </ClientOnly>

注意,这不会修复 导入时 访问 Browser APIs 的组件或库,假定要在导入时使用浏览器环境的代码,你需要在适当的生命周期钩子中动态地导入它们:

  1. <script>
  2. export default {
  3. mounted() {
  4. import('./lib-that-access-window-on-import').then((module) => {
  5. // use code
  6. })
  7. }
  8. }
  9. </script>

如果你的模块中是以 export default 声明的 Vue 组件,就可以动态注册:

  1. <template>
  2. <component v-if="dynamicComponent" :is="dynamicComponent"></component>
  3. </template>
  4. <script>
  5. export default {
  6. data() {
  7. return {
  8. dynamicComponent: null
  9. }
  10. },
  11. mounted() {
  12. import('./lib-that-access-window-on-import').then((module) => {
  13. this.dynamicComponent = module.default
  14. })
  15. }
  16. }
  17. </script>

另请参阅: