代码 Element-Plus-X:给 Vue 3 + Element Plus 补一套 AI 聊天组件,以及 useXStream 的 SSE 解析细节

2026-10-29 21:31:45

Element-Plus-X:Vue 3 + Element Plus 的 AI 组件库,与 useXStream 流式 hook

项目信息

生态相关:element-ui-x(Vue 2 版本)、hook-fetch(请求库)、ChatArea(轻量级聊天框)。

定位是企业级 AI 组件库,基于 Vue 3 + Element Plus,MIT 协议。特性上强调三点:聊天机器人与语音交互类组件、零配置接入 Element Plus 设计体系、按需加载与 Tree Shaking。

安装与引入

npm install vue-element-plus-x
pnpm add vue-element-plus-x
yarn add vue-element-plus-x

按需引入:


import { BubbleList, XSender } from 'vue-element-plus-x';
const list = [{ content: 'Hello, Element Plus X', role: 'user' }];

全局引入:

import ElementPlusX from 'vue-element-plus-x';
app.use(ElementPlusX);

CDN 引入(README 注明「该方法有待测试」):


版本策略是 SemVer,latest 为稳定版、beta 为测试版,装测试版:pnpm install vue-element-plus-x@beta。

本地开发:

pnpm install
pnpm run dev:docs    # 文档
pnpm run dev:core    # Storybook
pnpm run build:core

组件与 Hooks 清单

组件:

  • Bubble 气泡消息组件(拓展)
  • BubbleList 气泡消息列表(拓展)
  • Conversations 会话管理组件(拓展)
  • Welcome 欢迎组件
  • Prompts 提示集组件
  • FilesCard 文件卡片组件
  • Attachments 上传附件组件
  • XSender 智能输入框(含语音交互、提及功能)
  • Thinking 思考中组件(拓展)
  • ThoughtChain 思考链组件

文档侧边栏另有:EditorSender 编辑输入框、XMarkdown 渲染组件、Sender 输入框、MentionSender 提及输入框、Typewriter 打字器。

Hooks:

  • useRecord:基于浏览器内置语音识别 API 的 Hooks
  • useXStream:流模式接口 Hooks
  • useSend & XRequest:流模式 hooks 的拆分(拓展)

useXStream

这个 hook 负责流式请求的全流程控制:发起请求、中断请求、返回 loading 状态、返回 SSE 协议下的实时数据流、返回 error 信息。它对标 ant-design-x 的 XStream,融合 Vue 开发范式,新增流式中断处理,并把原配置项收进 startStream 的入参。

文档注明:目前只测试了 SSE 和 SIP 协议请求,其他协议还有待测试。

SSE 基础用法

import { useXStream } from 'vue-element-plus-x';

const { startStream, cancel, data, error, isLoading } = useXStream();

async function startSSE() {
try {
const response = await fetch('https://node-test.element-plus-x.com/api/sse', {
headers: { 'Content-Type': 'text/event-stream' }
});
const readableStream = response.body;
await startStream({ readableStream });
} catch (err) {
console.error('Fetch error:', err);
}
}

注意这里的前提:请求本身由业务侧用 fetch 发出,hook 接收的是 response.body 这个 ReadableStream,不是 URL。也就是说,鉴权、header、参数拼装都在自己的 fetch 里完成。

数据拼接:

const content = computed(() => {
if (!data.value.length) return '';
let text = '';
for (let index = 0; index  void` | 发起流式请求,可传入自定义 TransformStream |
| `cancel` | `() => void` | 中断当前流式请求 |
| `isLoading` | `Ref` | 是否正在请求(文档标题写作 `loading`,示例解构用 `isLoading`) |
| `data` | `Ref>` | 实时返回的流式数据,元素取 `data.value[index].data` |
| `error` | `Ref` | 流式请求的报错信息,可读 `error.message` |

### 默认解析规则

解析规则与 ant-design-x 一致,全部在 hook 内部完成,业务侧拿到的已经是拆好的 `data` 数组:

| 常量 | 值 | 作用 |
| --- | --- | --- |
| `DEFAULT_STREAM_SEPARATOR` | `'\n\n'` | 分割一条流数据 |
| `DEFAULT_PART_SEPARATOR` | `'\n'` | 换行当前数据 |
| `DEFAULT_KV_SEPARATOR` | `':'` | 键值对分隔 |
| `data:` 前缀 | — | SSE 字段前缀 |
| `[DONE]` | — | 结束标识,由后端决定是否返回 |

SSE 事件样例:

event: message
data: {"id":"${i}","content":"${contentChunks[i]}"}


### 非 SSE 协议:自定义 TransformStream

SIP 之类不符合 SSE 格式的协议,同样先 `fetch` 拿到 `response.body`,再自己构造 TransformStream 处理分片:

```js
const sipTransformStream = new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk);
}
});

await startStream({ readableStream, transformStream: sipTransformStream });

transformStream 的职责是把原始分片整理成 hook 能按默认规则解析的形态,格式对齐的工作放在这里,而不是散在业务代码里。

已知边界

  • 协议支持:文档明确只测过 SSE 与 SIP,其余协议待测。
  • CDN 引入方式在 README 中标注「有待测试」,生产接入优先走 npm 包。
  • [DONE] 是否出现由后端决定,前端解析循环里需要自己兜住这个分支。
  • data 里的每一项是 hook 拆好的单条 chunk,JSON.parse 失败通常意味着后端返回的不是约定结构,或流已结束。
复制全文 生成海报 Vue 3 Element Plus AI 组件 SSE 流式请求

推荐文章

程序员茄子在线接单