标签拦截
<StreamContains> 的默认插槽中放入的组件会被自动注册为标签拦截器。
组件注册
vue
<StreamContains :model-value="text">
<Think />
<CodeBlock />
</StreamContains>上述代码注册了两个拦截器:
<think>映射到Think组件<code-block>映射到CodeBlock组件
命名规则
buildComponentMap 通过组件定义中的 name(或 __name)提取组件名,支持:
- 大小写不敏感:
CodeBlock、code-block、codeblock都匹配<code-block> - 递归扫描:会穿透
Fragment、嵌套数组、子 VNode 的 children
ts
// 内部 normalizeTagName 做 toLowerCase
// toKebabCase 将 PascalCase 转为 kebab-case未注册标签
未匹配到组件的标签使用 DefaultTag 渲染:一个带标签名标头和灰底样式的容器。
子组件 Props
被拦截的组件自动注入以下 Props:
| 属性 | 类型 | 说明 |
|---|---|---|
block | StreamBlockData | 区块的完整结构化数据 |
attrs | Record<string, string | boolean> | 标签属性 |
content | string | 标签内文本内容(随流式增长) |
isClosed | boolean | 标签是否已闭合 |
reportData | (payload: unknown) => void | 回传数据至 block.payload |
属性解析
parseTagAttrs 支持四种属性格式:
html
<code lang="ts" theme='dark' line=12 disabled />
<!-- 双引号 单引号 无引号 布尔值 -->解析结果:{ lang: 'ts', theme: 'dark', line: '12', disabled: true }
嵌套拦截
Accurate 模式下,嵌套标签会被递归解析:外层的 default 插槽中包含内层组件的渲染结果。
html
<card><think>思考过程</think></card>若注册了 Card 和 Think,Think 会出现在 Card 的 default 插槽中。