当前位置: 首页 > news >正文

【流式输出】基于Vue实现增量渲染

随着AI应用的逐步普及,流式输出(Streaming Output)成为AI交互中的关键技术,指模型在生成完整回答前逐步、分块返回部分内容,类似“逐字输出”的效果。

一、SSE和websocket

实现流式输出,首先要选择合适的流式传输协议。那么常用的协议就是SSE和Websocket两种。

SSE(Server-Sent Events)与 WebSocket 对比

特性SSE(Server-Sent Events)WebSocket
通信方向单向(服务器 → 客户端)全双工(服务器 ↔ 客户端)
协议基于 HTTP(长轮询)独立协议(ws://wss://
数据格式纯文本(可自定义格式,如 JSON)二进制或文本
连接开销低(复用 HTTP 连接)较高(需独立握手)
断线重连自动支持(客户端内置重试机制)需手动实现
浏览器兼容性除 IE 外主流浏览器均支持主流浏览器均支持(包括 IE 10+)
适用场景实时通知、股票行情、新闻推送等在线聊天、游戏、实时协作等
实现复杂度简单(无需额外协议)较复杂(需处理握手、帧协议等)
安全性依赖 HTTPS支持 wss://(加密)
数据量支持适合高频小数据流适合大数据或二进制传输

关键差异总结

  • SSE 适合服务器主动推送数据的场景,如实时监控或日志流。
  • WebSocket 适合需要双向交互的场景,如即时通讯或多人协作工具。
  • SSE 默认不支持二进制数据,输出的是文本(UTF-8)流,而 WebSocket 支持灵活的数据类型。

在通用场景下,AI问答采用SSE协议即可满足业务需求、并且可以有效减小服务器的压力,省去了那些握手建立双向连接的过程。

而websocket通常用于在线文档多人协同、在线聊天室等复杂场景。

二、简单实现流式渲染

那么我们从SSE拿到了服务器推送的回答文本流,怎么实现流式渲染呢?

其实,“流式”只要服务端对数据作好分块推送,本身就已经达到流式效果了

所以简单来说,我们只需将输出内容拼好,放入v-html中渲染即可

// html
<div v-html="context"></div>//script
const context = ref('')
sse.onmessage = (event) => {context.value += JSON.parse(event.data)
}
⚠️注意

注意后端返回的文本流格式

  • 纯文本内容:需要自己组织dom结构
  • html字符串:直接放入
  • markdown:可以通过marked.js去解析markdwon,使其转换为html字符串

三、基于Vue的diff更新机制,实现增量渲染

Vue的diff算法大家一定不陌生,它是通过双端对比和就地复用策略高效更新虚拟DOM的算法。通俗来说,它会比较各个Vnode对象的信息,如果没有改变则不更新,只更新有改变的对象。减少不必要的重排重绘

那么利用这个机制呢?

我们需要把握怎么去生成一个虚拟Vnode,通过底层的diff算法来控制dom的更新

在 Vue 中,模板(<template>)其实只是语法糖,最终 Vue 都会把模板编译成 render 函数

也就是说,render 是模板的“底层实现形式”,它定义了组件应该如何被“渲染成虚拟 DOM(VNode)”

抓住这个,我们就可以显示的用h函数去创建Vnode、调用render函数去渲染Vnode,底层就会自动依照diff执行增量渲染

import { defineComponent, h } from 'vue'
import { parseDocument } from 'htmlparser2'
import { marked } from '@/config/markdown'const mapper = (node: any) => {if (node.type === 'text') {return node.data} else {return h(node.tagName, node.attribs, node.children.map(mapper))}
}export default defineComponent({name: 'Markdown',props: {markdown: {type: String,required: true,},},render(props: { markdown: string }) {const htmlString = marked(props.markdown) as stringconst nodes = parseDocument(htmlString).childrenreturn h('section',{ class: 'markdown' }, nodes.map(mapper))},
})

上述代码中,mapper函数是一个递归解析dom节点的函数

例如一个这样的html,

<h1>标题</h1>
<p>这是一段<strong>粗体</strong>文本。</p>

经过mapper的递归解析之后,会得到以下的h函数关系:

h('h1', {}, ['标题'])
h('p', {}, ['这是一段', h('strong', {}, ['粗体']), '文本。'])

http://www.dtcms.com/a/490821.html

相关文章:

  • 秦皇岛网站制作费用sns网站社区需求分析文档
  • 【AI论文】面向高效规划与工具使用的流程内智能体系统优化
  • html好看的网站的代码网站加图标
  • conda常用命令pip、venv
  • Visual Studio 2022查看程序变量和堆栈
  • RabbitMQ消息传输中Protostuff序列化数据异常的深度解析与解决方案
  • SSH连接服务器超时?可能原因与解决方案
  • iOS 代上架实战指南,从账号管理到使用 开心上架 上传IPA的完整流程
  • Visual Studio下的内存安全检测:CRT 内存泄漏 AddressSanitizer
  • iOS混淆与IPA文件加固深度解析,从反编译风险到苹果应用安全工程实践
  • 眉山建设中等职业技术学校 网站公司网页制作费用大概要多少钱?
  • 张店网站制作首选专家计算机大专生的出路
  • 万网的网站建设广州互联网公司集中在哪个区
  • 数据安全系列7:常用的非对称算法浅析
  • uniapp微信小程序+vue3基础内容介绍~(含标签、组件生命周期、页面生命周期、条件编译(一码多用)、分包))
  • 微信小程序报错 ubepected character `的style换行问题
  • H5封装打包小程序助手抖音快手微信小程序看广告流量主开源
  • 金华建设局网站做爰片在线看网站
  • 如何做二维码链接网站虚拟空间的网站赚钱吗
  • 营业部绩效考核方案与管理方法
  • 光刻刻蚀工艺控制要点及材料技术进展与限制
  • VPS SSH密钥登录配置指南:告别密码,拥抱安全
  • 注入“侨动力” 锻造“湘非链”
  • 做网站自己申请域名还是建站公司菏泽最好的网站建设公司
  • 网站建设方面书籍温州网站建设案例
  • 【Linux】Linux 零拷贝技术全景解读:从内核到硬件的性能优化之道
  • 微软ML.NET技术详解:从数据科学到生产部署的全栈解决方案
  • 镇江网站搜索引擎优化做外贸雨伞到什么网站
  • 网站收录一般多久沈阳建设学院
  • C++ AI 编程助手