打造一个支持流式输出的 Vue Markdown 渲染组件

打造一个支持流式输出的 Vue Markdown 渲染组件

在构建类似 ChatGPT 的对话交互界面时,我发现 Vue 社区缺乏一个原生支持流式 Markdown 渲染 的方案。而在 React 社区,很多人会使用 react-markdown 来实现类似需求。

react-markdown 的底层原理其实不复杂:它将 Markdown 文本解析为 markdown AST,再转换为 HTML AST,最后通过 React 的虚拟 DOM 机制将其渲染为 React 元素。这种方式充分利用了 React 的 Reconciliation 特性,在性能上表现非常优秀。

受此启发,我参考其实现方式,开发了一个 Vue 版本的流式 Markdown 渲染组件。

大概功能

  • 流式输出支持:模拟大语言模型逐字输出的效果,支持按粒度拆分内容逐步渲染
  • 高亮美观 :集成 shiki 实现语法高亮,且也支持流式处理
  • 性能优异 :基于 Vue 的虚拟 DOM 实现渐进渲染,性能显著优于直接使用 v-htmlmarkdown-it

安装方式

bash 复制代码
npm install vue-mdr

快速上手

1. 根据拆分的chunk,添加自定义的动画

css 复制代码
/* animation.css */
.vue-markdown-wrapper > *,
.vue-markdown-wrapper .text-segmenter,
.vue-markdown-wrapper .shiki-stream span {
  animation: fade-in 0.5s ease-in-out;
}

@keyframes fade-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

2. 使用示例

vue 复制代码
<script setup>
import { VueMarkdownRenderer } from "vue-mdr";
import { ref, onMounted } from "vue";
import "./animation.css";

// 创建模拟流式输出的函数
function createStream(text, chunkSize = 10, delay = 50) {
  let position = 0;
  return new ReadableStream({
    async pull(controller) {
      if (position >= text.length) {
        controller.close();
        return;
      }
      const chunk = text.slice(position, position + chunkSize);
      position += chunkSize;
      controller.enqueue(chunk);
      await new Promise((r) => setTimeout(r, delay));
    },
  });
}

const mdText = ref("");
const isRender = ref(true);

async function clickHandle() {
  mdText.value = "";
  isRender.value = true;
  const res = await fetch("./md.md");
  const md = await res.text();
  const stream = createStream(md);
  for await (const chunk of stream) {
    mdText.value += chunk;
  }
  isRender.value = false;
}

onMounted(clickHandle);
</script>

<template>
  <div>
    <button @click="clickHandle" :disabled="isRender">Re-generate ~</button>
    <article class="vue-markdown-wrapper">
      <VueMarkdownRenderer :md="mdText" />
    </article>
  </div>
</template>

为什么不用现成的库?

  • markdown-it 等常用库 不支持流式渲染
  • 现有方案缺乏良好的 动画与高亮支持
  • 大多数 Markdown 渲染方式依赖 v-html性能和可控性都较差

因此我将 Vue、Shiki 和流式渲染机制组合,封装出这个高效、美观、易用的 Markdown 渲染组件。开发者只需几行代码,就能轻松实现类似 AI 对话的「边输出边渲染 + 高亮 + 动画」效果。

项目结构简介

  • VueMarkdownRenderer.ts:组件主入口,核心的响应式渲染逻辑
  • segmentText.ts:文本拆分与动画粒度处理模块

最后

虽然 vue-mdr 的实现并不复杂,但它显著提升了我的开发效率和终端用户体验。如果你正在做 AI 聊天、内容生成、知识库问答等应用,这个组件或许正好适合你!

相关推荐
Definition4 分钟前
在 Windows 中新增 Markdown(.md)右键新建项并修改默认图标
markdown
拾光拾趣录4 分钟前
从“祖传”构造函数到 `class`
前端·javascript
wmm_会飞的@鱼8 分钟前
FlexSim-汽车零部件仓库布局优化与仿真
服务器·前端·网络·数据库·数学建模·汽车
yvvvy10 分钟前
从“按钮都不会点”到“能撸大厂 UI”:我用 react-vant 踢开组件库的大门!
前端·javascript
安然dn11 分钟前
Cropper.js:JS图像裁剪库
前端·javascript
Serendipity26113 分钟前
微服务架构
前端·微服务
Hilaku28 分钟前
深入background-image:你可能不知道的几个性能优化与高级技巧
前端·css
南岸月明31 分钟前
副业自媒体1年终于明白:为什么会表达的人,能量越来越强,更能赚到钱?
前端
Danny_FD44 分钟前
Vue + Element UI 实现模糊搜索自动补全
前端·javascript
gnip1 小时前
闭包实现一个简单Vue3的状态管理
前端·javascript