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

相关推荐
青皮桔1 分钟前
CSS实现百分比水柱图
前端·css
影子信息6 分钟前
vue 前端动态导入文件 import.meta.glob
前端·javascript·vue.js
青阳流月7 分钟前
1.vue权衡的艺术
前端·vue.js·开源
样子201811 分钟前
Vue3 之dialog弹框简单制作
前端·javascript·vue.js·前端框架·ecmascript
kevin_水滴石穿12 分钟前
Vue 中报错 TypeError: crypto$2.getRandomValues is not a function
前端·javascript·vue.js
c++服务器开发30 分钟前
一文详解Character AI:实用指南+ ChatGPT、Gemini对比分析
人工智能·chatgpt
孤水寒月1 小时前
给自己网站增加一个免费的AI助手,纯HTML
前端·人工智能·html
CoderLiu1 小时前
用这个MCP,只给大模型一个figma链接就能直接导出图片,还能自动压缩上传?
前端·llm·mcp
伍哥的传说1 小时前
鸿蒙系统(HarmonyOS)应用开发之实现电子签名效果
开发语言·前端·华为·harmonyos·鸿蒙·鸿蒙系统
海的诗篇_2 小时前
前端开发面试题总结-原生小程序部分
前端·javascript·面试·小程序·vue·html