本文同步在个人博客shymean.com上,欢迎关注
由于掘金上面不支持mdx,所以部分演示功能会有问题,可以移步原文章
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代码块,会使用下面的语法
python
'''vue
<template>
<button>原始code</button>
</template>
'''
内联Vue组件,是在vue代码块的基础上,通过一个JSON字符串配置component
字段为true来开启的
xml
'''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组件,不需要引入任何的外部文件!!
当前页面就是由这个功能来实现的,不出意外的话,你可以在下面看见一个通过该方式渲染的内联组件。
(由于掘金上面不支持mdx,所以部分演示功能会有问题,使用图片进行了代替,可以移步原文章查看具体效果)
内联组件跟单独创建的SFC文件完全相同,可以访问当前开发环境,比如ts
、unocss
、其他组件或工具模块等。
name组件名
还支持另外一个name
的字段,指定之后,sfc代码块会编译成对应名称的组件,然后你可以使用该组件名,在本页面的其他地方进行复用
。
当然,你需要保证该组件名在当前文档下唯一
。
python
'''vue { "component": true, "name": "Demo" }
here your sfc code
'''
一些内容之后,通过组件名复用
<Demo />
通过<componentName />
的形式调用,就像是引入了一个外部组件
下面演示了复用在上一个章节定义的内联组件,你应该会看见一个与上面完全一样的组件渲染节点。
lazy
在默认情况下,开启了component:true
的代码块,会直接在该代码块的位置渲染出对应的组件。
这是sfc代码块最常见的场景,即不需要从外部引入模块文件,就可以为当前模块编写组件。
如果在某种情况下,你希望先编写代码,但是不希望立即渲染,可以手动打开lazy:true
配置项。
python
'''vue { "component": true, "name": "Demo2", "lazy": false }
here your sfc code
'''
一些内容之后,通过组件名手动渲染
<Demo2 />
开启后,你需要手动通过name
来编写组件标签进行渲染。
源文件中,这里有一段代码,但没有立即渲染。
(这里有一大段内联组件代码)
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>
你需要手动编写<Demo2 />
标签,之后该组件才会渲染
导入代码片段
同时展示交互组件和对应源码是比较常见的需求,vitepress提供了导入代码片段的功能
bash
<<< @/filepath
由于上述sfc组件并不存在对应的组件,为了兼容该语法,定制了一个特殊的>>>
语法
arduino
>>> virtual:xxComponentName
比如展示上面的Demo2组件源码,路径修改为virtual:Demo2
,就会展示如下源码
xml
<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>
使用
安装
arduino
// 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或者评论区讨论交流。