StreamContains
核心容器组件,解析流式文本、拦截标签、分发渲染。
Props
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
model-value / v-model | string | '' | 待解析的原始流式文本 |
mode | 'fast' | 'accurate' | 'accurate' | 解析模式 |
data / v-model:data | StreamBlockData[] | [] | 结构化数据双向绑定 |
components | Record<string, Component> | {} | 显式注册标签组件 |
base-component | Component | null | null | 统一包裹所有区块的组件 |
Events
| 事件 | 参数 | 说明 |
|---|---|---|
update:data | StreamBlockData[] | 结构化区块数据更新 |
parse-warning | string | Accurate 模式检测到标签交错或孤立闭合标签时触发 |
子组件 Props
被拦截的组件接收以下 Props:
| 属性 | 类型 | 说明 |
|---|---|---|
block | StreamBlockData | 区块完整数据 |
attrs | Record<string, string | boolean> | 标签属性 |
content | string | 标签内文本(随流式增长) |
isClosed | boolean | 标签是否已闭合 |
reportData | (data: any) => void | 回传数据至 block.payload |
标签注册
默认插槽中的组件按 name 或 __name 自动注册。
vue
<StreamContains :model-value="text">
<Think />
<CodeBlock />
</StreamContains>也可以通过 components 显式注册,适合组件来自自动导入、配置对象或不想渲染注册用插槽的场景。
vue
<script setup>
import { StreamContains, Think, Code } from '@huiol/stream-ui'
const components = {
think: Think,
code: Code
}
</script>
<template>
<StreamContains :model-value="text" :components="components" />
</template>- 命名大小写不敏感:
CodeBlock/code-block/codeblock都匹配<code-block> - 默认插槽和
components会合并;同名时components显式注册优先 - 未注册标签由
DefaultTag降级渲染
StreamBlockData
ts
interface StreamBlockData {
id: string
tagName: string
attrs?: Record<string, string | boolean>
content: string
isClosed: boolean
category: 'component' | 'fallback' | 'text'
payload?: unknown
}标签上的字符串 id 属性会优先作为区块 ID,便于在 v-model:data 中稳定追踪 payload。
html
<input-block id="email" label="邮箱" />baseComponent 插槽
| 插槽 | 说明 |
|---|---|
default | 原始渲染结果(VNode) |
raw | 区块的纯文本内容(字符串) |
vue
<script setup>
const Base = defineComponent({
setup(props, { slots }) {
return () => h('div', [
slots.default?.(), // 渲染结果
h('pre', slots.raw?.()) // 原始文本
])
}
})
</script>注意事项
v-model:data更新合并到queueMicrotask中执行,避免高频重复触发- 相同文本的重复渲染会跳过 emit(
areBlocksEqual对比) - Accurate 模式下的解析警告会触发
parse-warning,并同时在console.groupCollapsed中输出