侧边栏

在VitePress中实现内联Vue组件

发布于 | 分类于 技术原理

VitePress默认就支持在markdown中使用Vue组件,唯一的缺点是需要单独将SFC组件文件引入。

本文将探究一种新的方式,直接在markdown文档中编写Vue组件。

背景

VitePress默认执行在markdown文件中使用vue组件,参考文档:在 Markdown 使用 Vue

对于有前端经验的开发者来说,这个功能可以增强整个文档的交互,也是我非常喜欢VitePress的特性之一。

唯一的缺点是:引入的组件需要单独使用文件来进行管理

vue
<script setup>
import CustomComponent from '../../components/CustomComponent.vue'
</script>

比如上面这段写法,你需要手动管理这些外部组件,大概的流程可能是:创建一个components目录,然后将这个CustomComponent.vue组件实现。

如果这个组件会在大多数markdown文件中使用,这样做是很正常的事情。

但在使用VitePress搭建自己的博客站点时发现,markdown中的某些组件,往往只会跟当前的文档内容插入该组件时的上下文联系紧密,用于演示该文档的特定内容。

对于这种用途的组件,将他们放在单独的文件里面,然后通过script setup引入注册,感觉上并不是一种很好的做法:当单独阅读组件内容时,可能会丢失markdown文档中的上下文部分。

对于一个分类比较杂乱的博客来说,看起来需要一种更好的管理这些外部组件的方式。

因此,我决定开发一种类似于内联的vue代码块语法,可以直接在markdown中以SFC代码块的方法直接编写组件,这样就不需要手动管理外部组件文件,以及导入他们的逻辑了。

暂且将这种特殊的vue代码块语法称作内联Vue组件

配置

component开启内联

正常编写一个vue代码块,会使用下面的语法

```vue
<template>
  <button>原始code</button>
</template>
```

内联Vue组件,是在vue代码块的基础上,通过一个JSON字符串配置component字段为true来开启的

```vue { "component": true } 
<script setup lang="ts">
import { add } from './util'
const onClick = ()=>{
    alert("click me")
}
</script>

<template>
  <button class="bg-red-100" @click="onClick">click me</button>
</template>

<style scoped>
button {
    color: red;
}
</style>
```

上述的{ "component": true }会将vue代码块进行扩展,通过vite插件构建为一个在markdown里面运行的vue SFC组件,不需要引入任何的外部文件!!

当前页面就是由这个功能来实现的,不出意外的话,你可以在下面看见一个通过该方式渲染的内联组件。

内联组件跟单独创建的SFC文件完全相同,可以访问当前开发环境,比如tsunocss、其他组件或工具模块等。

name组件名

还支持另外一个name的字段,指定之后,sfc代码块会编译成对应名称的组件,然后你可以使用该组件名,在本页面的其他地方进行复用

当然,你需要保证该组件名在当前文档下唯一

```vue { "component": true, "name": "Demo" }
here your sfc code
```

一些内容之后,通过组件名复用

<Demo />

通过<componentName />的形式调用,就像是引入了一个外部组件

下面演示了复用在上一个章节定义的内联组件,你应该会看见一个与上面完全一样的组件渲染节点。

lazy

在默认情况下,开启了component:true的代码块,会直接在该代码块的位置渲染出对应的组件。

这是sfc代码块最常见的场景,即不需要从外部引入模块文件,就可以为当前模块编写组件。

如果在某种情况下,你希望先编写代码,但是不希望立即渲染,可以手动打开lazy:true配置项。

```vue { "component": true, "name": "Demo2", "lazy": false }
here your sfc code
```

一些内容之后,通过组件名手动渲染

<Demo2 />

开启后,你需要手动通过name来编写组件标签进行渲染。

源文件中,这里有一段代码,但没有立即渲染。

(这里有一大段内联组件代码)

你需要手动编写<Demo2 />标签,之后该组件才会渲染

导入代码片段

同时展示交互组件和对应源码是比较常见的需求,vitepress提供了导入代码片段的功能

<<< @/filepath

由于上述sfc组件并不存在对应的组件,为了兼容该语法,定制了一个特殊的>>>语法

>>> virtual:xxComponentName

比如展示上面的Demo2组件源码,路径修改为virtual:Demo2,就会展示如下源码

vue
<script setup lang="ts">
import { add }from'./util'
const onClick = ()=>{
    alert("click me")
}
</script>

<template>
  <button class="bg-red-100" @click="onClick">click me demo2</button>
</template>

<style scoped>
button {
    color: red;
}
</style>

其他

该功能目前已发布到npm上面,源代码位于github上面

安装

// npm
npm i vite-plugin-vitepres-inline-sfc -D
// pnpm 
pnpm i vite-plugin-vitepres-inline-sfc -D

.vitepress/config.mts中作为vite插件引入

js
import { defineConfig } from 'vitepress'
import inlineSFC from 'vite-plugin-vitepres-inline-sfc'

export default defineConfig({
  ... other vitepress config
  vite: {
    plugins:[
      inlineSFC()
    ]
  }
})

我已经自己的博客中尝试使用该功能,目前体验下来还不错,可以在一个markdown文件中编写内容和交互组件,不需要额外管理单独的组件文件。

如果有什么问题,或者新功能建议,欢迎在issue或者评论区讨论交流。

你要请我喝一杯奶茶?

版权声明:自由转载-非商用-保持署名和原文链接。

本站文章均为本人原创,参考文章我都会在文中进行声明,也请您转载时附上署名。