
Quasar 框架 QChatMessage 聊天气泡组件完全指南Props、Slots、HTML 安全与无障碍实践【免费下载链接】quasarQuasar Framework - Build high-performance VueJS user interfaces in record time项目地址: https://gitcode.com/gh_mirrors/qu/quasar导读QChatMessage 是 Quasar Framework 提供的一款单条聊天消息条目组件它负责把作者名、头像、消息正文、时间戳和日期分隔标签等数据渲染成完整的聊天气泡 UI开箱即用地支持自己发送sent与对方接收received两种视觉形态。本文以官方文档 chat.md 为主线逐项讲解全部 14 个 Props、5 个 Slots 的用法并结合仓库内的示例与源码实现深入剖析组件的渲染原理、HTML 注入风险与无障碍Accessibility设计。读完本文你将能够用 QChatMessage 快速搭建专业、安全、可访问的聊天界面。组件定位一条消息而不是整个聊天窗口QChatMessage 的定位非常聚焦——它只是一个聊天条目chat entry负责把 Props 传入的数据渲染成单条气泡消息并不包含消息列表、输入框、滚动容器等完整 IM 能力。真实场景中你通常用v-for循环渲染多条q-chat-message外层再包上你自选的滚动容器和输入区。[!TIP] 当同一会话中部分消息带头像、部分不带时为了让所有气泡对齐建议为无头像的消息使用一张占位头像图片。Props 全解数据驱动的气泡渲染依据 QChatMessage.json 中的 API 定义组件共有 14 个 Props可按作用分为内容与样式两类Prop类型默认值说明sentBooleanfalse是否渲染为自己发送的消息内容靠右、颜色区分labelString—只渲染一个标签头部/分隔行如日期不渲染气泡nameString—消息作者的名字avatarString—作者头像图片 URLtextArray—消息正文为字符串数组每项渲染为一段文本stampString—创建时间戳文本如13:55、Yesterday at 13:51bg-colorString—气泡背景色取值来自 Quasar 调色板text-colorString—气泡文字颜色同样来自调色板sizeString—气泡占据的栅格宽度1–12同col-*栅格语义label-htmlBooleanfalse以 HTML 渲染label存在 XSS 风险name-htmlBooleanfalse以 HTML 渲染name存在 XSS 风险text-htmlBooleanfalse以 HTML 渲染text存在 XSS 风险stamp-htmlBooleanfalse以 HTML 渲染stamp存在 XSS 风险其中avatar的 URL 写法非常灵活源码声明了transformAssetUrls: true因此以下形式都合法!-- 放在 public 目录直接引用 -- q-chat-message avatarboy-avatar.png / !-- 放在 assets 目录通过模块解析 -- q-chat-message avatar~/assets/boy-avatar.png / !-- 相对路径格式 -- q-chat-message :avatarrequire(./my_img.jpg) / !-- 远程 URL -- q-chat-message avatarhttps://picsum.photos/500/300 /text是字符串数组数组中的每一项会被渲染为一段独立的文字节点天然支持一条消息多条分段的场景见下文 Size 示例中的超长消息拆分。基础用法从空白气泡到完整消息以下示例均可在仓库的 docs/src/examples/QChatMessage 目录中找到完整源码。最简形态只有正文只传text数组即可渲染气泡配合sent区分发送方与接收方q-chat-message :text[hey, how are you?] sent / q-chat-message :text[doing fine, how r you?] /sent语义上代表当前用户发送的消息渲染为右侧对齐不加sent的消息则作为对方接收的消息渲染在左侧。完整示例见 Basic.vue。作者名name通过name在气泡上方标注作者q-chat-message nameme :text[hey, how are you?] sent / q-chat-message nameJane :text[doing fine, how r you?] /完整示例见 Name.vue。头像avatarq-chat-message nameme avatarhttps://cdn.quasar.dev/img/avatar1.jpg :text[hey, how are you?] sent / q-chat-message nameJane avatarhttps://cdn.quasar.dev/img/avatar2.jpg :text[doing fine, how r you?] /完整示例见 Avatar.vue。注意源码中头像img会被渲染为q-message-avatar q-message-avatar--sent|received类并带有aria-hiddentrue属性无障碍部分会详述。时间戳stampq-chat-message nameme avatarhttps://cdn.quasar.dev/img/avatar4.jpg :text[hey, how are you?] sent stamp7 minutes ago / q-chat-message nameJane avatarhttps://cdn.quasar.dev/img/avatar3.jpg :text[doing fine, how r you?] stamp4 minutes ago /stamp只是一段纯文本传入什么就显示什么你也可以在业务层自行格式化为绝对时间或相对时间。完整示例见 Stamp.vue。日期分隔标签labellabel用于在消息流中插入日期/分组标题——它只渲染一条水平居中的标签不渲染气泡q-chat-message labelSunday, 19th /完整示例见 Label.vue。从源码看label对应的 DOM 类名为q-message-label它被渲染在组件根节点之下、消息容器之上天然承担会话内分组分隔符的职责。定制颜色与尺寸文本与背景色bg-color与text-color直接接受 Quasar 调色板中的颜色名如primary、amber-7组件内部会拼接出text-color工具类q-chat-message nameme avatarhttps://cdn.quasar.dev/img/avatar1.jpg :text[hey, how are you?] stamp7 minutes ago sent bg-coloramber-7 / q-chat-message nameJane avatarhttps://cdn.quasar.dev/img/avatar5.jpg :text[doing fine, how r you?] stamp4 minutes ago text-colorwhite bg-colorprimary /完整示例见 Color.vue。气泡宽度sizesize接受 1–12 的栅格值与col-*语义一致用于控制气泡在会话中的宽度占比。当消息较长时可以把它限制在例如6一半宽度短消息则用8或默认q-chat-message nameJane avatarhttps://cdn.quasar.dev/img/avatar5.jpg :text[ doing fine, how r you?, I just feel like typing a really, really, REALLY long message to annoy you... ] size6 stamp4 minutes ago text-colorwhite bg-colorprimary / q-chat-message nameJane avatarhttps://cdn.quasar.dev/img/avatar5.jpg :text[Did it work?] stamp1 minutes ago size8 text-colorwhite bg-colorprimary /从源码看size会被映射为col-${size}类名如col-6、col-8因此其栅格行为与 Quasar 栅格系统完全一致。完整示例见 Size.vue。Slots完全自定义气泡内容QChatMessage 提供 5 个插槽优先级均高于对应 Props——一旦使用插槽同名 Prop 即被忽略。插槽定义见 QChatMessage.json 的slots段。default 插槽自定义消息正文默认插槽会完全覆盖textprop允许你在气泡内放任意内容比如带表情图片的富文本、加载动画等q-chat-message nameme avatarhttps://cdn.quasar.dev/img/avatar3.jpg stamp7 minutes ago sent text-colorwhite bg-colorprimary div Hey there! /div div Have you seen Quasar? img altSurprised Quasar emoji srchttps://cdn.quasar.dev/img/discord-omq.png classmy-emoticon / /div /q-chat-message q-chat-message nameJane avatarhttps://cdn.quasar.dev/img/avatar5.jpg bg-coloramber q-spinner-dots size2rem / /q-chat-message第二个气泡用q-spinner-dots模拟对方正在输入…的等待态这是默认插槽的典型实战用法。完整示例见 SlotDefault.vue。avatar / name / stamp 插槽逐块替换这三个插槽分别覆盖头像、名字和时间戳。注意官方示例提示使用avatar插槽时建议自行为图片添加q-message-avatar q-message-avatar--sent|received类以保持与 Prop 渲染一致的外观q-chat-message :text[Have you seen Quasar?] sent text-colorwhite bg-colorprimary template #nameme/template template #stamp7 minutes ago/template template #avatar img altUser avatar classq-message-avatar q-message-avatar--sent srchttps://cdn.quasar.dev/img/avatar4.jpg / /template /q-chat-message完整示例见 SlotAvatarStampName.vue。此外 JSON 定义中还包含label插槽可自定义日期分隔标签内容。SanitizationHTML 注入安全警示组件提供label-html、name-html、text-html、stamp-html四个渲染原始 HTML开关。源码中对应的实现是h(div, { class: q-message-name q-message-name--${op}, [props.nameHtml ? innerHTML : textContent]: props.name })即默认走textContent纯文本安全只有显式开启*-html后才走innerHTML原始 HTML危险。官方文档对此给出明确警告[!WARNING] 如果你不信任值的来源例如值来自用户输入请务必先对内容进行消毒sanitize。看下面的对比示例完整版见 Sanitize.vue!-- 默认name 中的 HTML 标签会被当作纯文本显示 -- q-chat-message namespan classtext-positiveUntrusted Source/span :text[hey, how are strongyou/strong?] sent / !-- 开启 name-html标签被渲染但如果内容不可信则存在 XSS 风险 -- q-chat-message namespan classtext-negativeJane (trusted name but untrusted text)/span name-html :text[doing fine, how r you?] sent / !-- 同时开启 name-html 与 text-html -- q-chat-message namespan classtext-negativeJao (trusted)/span name-html :text[strongDid it work?/strong] text-html sent /安全实践建议来自服务端/其他用户的消息正文默认不要开text-html直接传纯文本即可确实需要富文本如表情、链接时务必先用 DOMPurify 等库对字符串消毒后再传入名字、时间戳、日期标签同理非必要不开*-html。Accessibility无障碍与可访问性设计v2.25从 v2.25 起QChatMessage 强化了无障碍支持chat.md 中对此有专门一节说明正文是纯文本内容屏幕阅读器可直接朗读头像图片对辅助技术隐藏——源码中头像img硬编码了aria-hiddentrue见 QChatMessage.js避免装饰性图片干扰朗读发送/接收仅通过视觉对齐方向与颜色传达屏幕阅读器无法感知方向差异因此必须提供nameprop 或等价的文本内容让消息作者是谁能被正确播报。只靠对齐区分作者的可访问性是不足的。这条提醒对无障碍合规项目非常关键即便视觉上靠左右对齐就能分清对话双方也请始终为每条消息设置name或用#name插槽提供文本。源码剖析一条消息如何被渲染QChatMessage.js 的实现非常轻量没有模板文件全部通过渲染函数render function输出 DOM核心逻辑集中在setup内方向标记const op props.sent ? sent : received决定所有内部类名后缀q-message--sent、q-message-avatar--sent、q-message-text--sent等与容器reverse类实现 Flex 行反转、气泡靠右头像优先级#avatar插槽 avatarprop渲染为带aria-hidden的img作者名优先级#name插槽 nameproptextContent/innerHTML二选一正文优先级#default插槽 textprop。使用默认插槽时若只有一个 VNode 会包一层div多个 VNode 则平铺渲染而text数组则对每个字符串生成独立的q-message-text气泡段落时间戳#stamp插槽 stampprop追加到每段正文之后尺寸sizeprop 映射为col-${size}日期标签#label插槽 labelprop渲染为q-message-label放在消息容器之前。最终的 DOM 骨架为q-message含q-message-sent/received修饰→q-message-labelq-message-containerrow items-end no-wrapsent时加reverse→ 头像 col-*内容列q-message-name、多个q-message-text每个内含q-message-text-content与可选q-message-stamp。所有样式类在 QChatMessage.sass 中定义你可以在自己的样式中覆写这些类来深度定制外观。仓库还为组件提供了完整的单元测试与 SSR 水合测试QChatMessage.test.js、QChatMessage.hydration.test.js可作为你理解各 Props 组合行为的参考。小结何时用 Props何时用 Slots需求推荐方式纯文本消息流、姓名、头像、时间Propstextnameavatarstamp富文本、图片、加载动画、自定义排版#default插槽特殊头像如 SVG、QAvatar 组件#avatar插槽动态作者名/时间如本地化格式#name/#stamp插槽日期分组labelprop 或#label插槽强调某条消息颜色、宽度bg-color/text-color/sizeQChatMessage 的设计哲学是数据驱动 插槽兜底常规文本场景一行 Props 即可复杂场景则用插槽完全接管。唯一需要你保持警惕的是*-html系列开关——它们是功能便利与安全责任的边界务必在渲染不可信内容前做好消毒。【免费下载链接】quasarQuasar Framework - Build high-performance VueJS user interfaces in record time项目地址: https://gitcode.com/gh_mirrors/qu/quasar创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考