如何完成前端对于AI回答的流式输出,markdown渲染,代码高亮等效果

3 阅读1分钟

一.依赖引入

import MarkdownIt from 'markdown-it'
import hljs from 'highlight.js'
  • markdown-it是对于AI回答进行md格式渲染的不二选择,highlight.js将配合markdown-it一起使用达到代码高亮的效果

二.渲染器准备

const markdownRender = new MarkdownIt({
  html: true,//允许渲染的的内容中有html结构
  linkify: true,//自动将文本中的URL转化成可点击的链接
  typographer: true,//美化标点符号
  breaks: true,//将单个换行符\n转换成<br>
  
  //str:代码块的纯文本内容,lang:代码块指定的语言,例如JavaScript
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
    //ignoreIllegals:忽略代码中可能存在的语法错误
      try {
        return '<pre class="hljs"><code>' +
               hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
               '</code></pre>'
      } catch (__) {}
    }
    //转义代码中的 HTML 特殊字符(比如`<`转成`&lt;`),防止代码中的标签被浏览器渲染,避免 XSS 风险;
    return '<pre class="hljs"><code>' + markdownRender.utils.escapeHtml(str) + '</code></pre>'
  }
})

三.获取AI回答数据并渲染

const streamUrl = new URL('你的后端AI服务地址')
streamUrl.searchParams.set('message''请给我回答')
const eventSource = new EventSource(streamUrl)
//开始消息监听
    eventSource.onmessage = (event) => {
      const content = event.data
      //如果结束了:
      if (content === '[DONE]') {
      //结束的函数,自定义
        handleComplete()
        return
      }
      //fullMarkdown:自定义变量
      fullMarkdown += content === '' ? '\n' : content
      //message:自定义对象数组,用于存储对话信息
      //currentAiMessageIndex:自定义变量,用于标识message数组的当前对话
      messages.value[currentAiMessageIndex].htmlContent = markdownRender.render(fullMarkdown)
      //滚动到最底部
      nextTick(() => {
      //chatMessagesRef:自定义对话dom容器变量
        chatMessagesRef.value?.scrollTo({
          top: chatMessagesRef.value.scrollHeight,
          behavior: 'auto'
        })
      })
    }