Sender组件交互设计涵盖三种提交快捷键、完整事件体系及焦点控制方法。核心事件submit支持纯文本与结构化数据双参数返回,cancel适配AI流式响应中断。通过submitType切换提交方式,方法调用实现程序化控制,Mention与Template扩展自动产出结构化数据。
在构建 AI 对话界面时,输入框的交互设计往往决定了用户体验的流畅度。Sender 组件在这方面做得相当灵活,但要想用好它,除了配置属性,还需要深入掌握其提交方式、快捷键、事件和方法这几个核心维度。下面从最基础的提交方式开始讲解。
Sender 提供了三种提交方式,通过 submitType 属性即可灵活切换。具体是哪三种?请看下表。
长期稳定更新的攒劲资源: >>>点此立即查看<<<

type SubmitTrigger = 'enter' | 'ctrlEnter' | 'shiftEnter'
| 配置值 | 提交快捷键 | 换行快捷键 | 适用场景 |
|---|---|---|---|
enter | Enter | Ctrl+Enter 或 Shift+Enter | 即时通讯、快速交互 |
ctrlEnter | Ctrl+Enter | Enter | 长文本编辑、邮件场景 |
shiftEnter | Shift+Enter | Enter | 与 ctrlEnter 互为替代 |
已提交: {{ submittedContent }}
单行模式(mode="single")下如果按了换行快捷键,输入框会自动切换到多行模式,这个设计很贴心:
submitType="enter" + mode="single"
→ 按 Enter:提交
→ 按 Ctrl+Enter 或 Shift+Enter:自动切换到多行模式并换行
除了提交相关的快捷键,Sender 还支持一系列导航和操作快捷键,整理如下:
| 快捷键 | 功能 | 适用条件 |
|---|---|---|
| Enter | 提交内容 / 换行 | submitType="enter" |
| Ctrl+Enter | 提交内容 / 换行 | submitType="ctrlEnter" / submitType="enter" |
| Shift+Enter | 提交内容 / 换行 | submitType="shiftEnter" / submitType="enter" |
| Tab | 选中联想项 | Suggestion 扩展开启时 |
| Esc | 关闭联想 | Suggestion 扩展开启时 |
| ↑ / ↓ | 导航联想项 | Suggestion 扩展开启时 |
| Backspace | 删除提及项 | Mention 扩展开启时 |
如果你对默认的 Enter/Tab 选中方式不满意,可以通过 Suggestion 扩展的 activeSuggestionKeys 自定义按键:
TrSender.Suggestion.configure({
items: suggestions,
activeSuggestionKeys: ['Enter', 'Tab'], // 默认支持 Enter 和 Tab
})
移动端场景下,虚拟键盘的回车键显示什么文字?用 enterkeyhint 属性控制:
type EnterKeyHint = 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send'
| 事件名 | 说明 | 回调参数 |
|---|---|---|
update:modelValue | 内容更新 | (value: string) |
submit | 提交内容 | (text: string, data: StructuredData) |
clear | 清空内容 | () |
focus | 获得焦点 | (event: FocusEvent) |
blur | 失去焦点 | (event: FocusEvent) |
input | 输入变化 | (value: string) |
cancel | 取消操作(loading 状态下) | () |
submit 是 Sender 最核心的事件,它同时返回两个参数——纯文本 text 和可选的结构化数据 data。先看简单场景,只取 text:
复杂场景下,比如使用了 Mention 扩展,data 里会包含特殊节点的结构化信息:
// Mention 扩展的结构化数据
function handleSubmit(text: string, data?: StructuredData) {
// text: "帮我分析 @张三 的周报"
// data: [
// { type: 'text', content: '帮我分析 ' },
// { type: 'mention', content: '张三', value: '用户ID' },
// { type: 'text', content: ' 的周报' }
// ]
// 提取所有提及项
const mentions = data?.filter(item => item.type === 'mention') || []
// 自定义 Slack 风格格式
const customText = data?.map(item =>
item.type === 'mention' `<@${item.value}>` : item.content
).join('')
}
当然,Template 扩展也能产出结构化数据,提取方式类似:
// Template 扩展的结构化数据
function handleSubmit(text: string, data?: StructuredData) {
// data: [
// { type: 'text', content: '帮我分析 ' },
// { type: 'block', content: '张三' },
// { type: 'text', content: ' 的周报' }
// ]
// 提取所有模板块
const blocks = data?.filter(item => item.type === 'block') || []
// 自定义 Mustache 风格格式
const customText = data?.map(item =>
item.type === 'block' `{{${item.content}}}` : item.content
).join('')
}
在 AI 响应场景中,用户可能需要中断正在进行的操作。用 cancel 事件处理取消逻辑:
| 事件 | 说明 | 回调参数 |
|---|---|---|
select | 文件选择成功 | (files: File[]) |
error | 文件验证失败 | (error: Error, file: File) |
| 事件 | 说明 | 回调参数 |
|---|---|---|
speech-start | 开始录音 | () |
speech-interim | 中间结果 | (transcript: string) |
speech-final | 最终结果 | (transcript: string) |
speech-end | 结束录音 | (transcript: string) |
speech-error | 识别错误 | (error: Error) |
| 方法 | 说明 | 参数 | 返回值 |
|---|---|---|---|
focus() | 使输入框获取焦点 | - | void |
blur() | 使输入框失去焦点 | - | void |
clear() | 清空输入内容 | - | void |
submit() | 手动触发提交 | - | void |
setContent(content) | 设置编辑器内容 | content: string | void |
getContent() | 获取编辑器内容 | - | string |
cancel() | 手动触发取消 | - | void |
| 方法 | 说明 | 参数 | 返回值 |
|---|---|---|---|
open() | 打开文件选择器 | - | void |
| 方法 | 说明 | 参数 | 返回值 |
|---|---|---|---|
start() | 开始录音 | - | void |
stop() | 停止录音 | - | void |
Sender 的交互体系设计遵循“灵活但可控”的原则:
掌握这些交互细节,在实际项目中就能精确控制输入行为,打造流畅的用户体验。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述