打造一个支持流式输出的 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 聊天、内容生成、知识库问答等应用,这个组件或许正好适合你!

相关推荐
我命由我1234511 分钟前
VSCode - Prettier 配置格式化的单行长度
开发语言·前端·ide·vscode·前端框架·编辑器·学习方法
HashTang11 分钟前
【AI 编程实战】第 4 篇:一次完美 vs 五轮对话 - UnoCSS 配置的正确姿势
前端·uni-app·ai编程
JIngJaneIL19 分钟前
基于java + vue校园快递物流管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js
asdfg125896336 分钟前
JS中的闭包应用
开发语言·前端·javascript
kirk_wang38 分钟前
Flutter 导航锁踩坑实录:从断言失败到类型转换异常
前端·javascript·flutter
静小谢1 小时前
前后台一起部署,vite配置笔记base\build
前端·javascript·笔记
用户47949283569152 小时前
改了CSS刷新没反应-你可能不懂HTTP缓存
前端·javascript·面试
还好还好不是吗2 小时前
老项目改造 vue-cli 2.6 升级 rsbuild 提升开发效率300% upupup!!!
前端·性能优化
sumAll2 小时前
别再手动对齐矩形了!这个开源神器让 AI 帮你画架构图 (Next-AI-Draw-IO 体验)
前端·人工智能·next.js