H5端仅支持基础消息收发,小程序和App端必须集成原生IM插件(如TXIM、融云、Zego-ZIM)以实现离线消息、语音通话及后台推送;自研WebSocket方案因多端限制不可行。

uni-app 开发仿微信聊天社交 App,核心不是“能不能做”,而是**哪些能力必须用原生插件、哪些能纯前端模拟、哪些交互在多端表现不一致**。直接结论:H5 端只能做基础消息收发;小程序和 App 端必须依赖原生 IM 插件(如 TXIM、ZIM 或 融云 SDK),否则无法实现离线消息、语音通话、后台消息推送等关键能力。
为什么不能只靠 uni.request + WebSocket 自己写 IM?
WebSocket 在 H5 可用,但在微信小程序中受限(uni.connectSocket 有域名白名单、不支持二进制帧、断连重试逻辑极难对齐)、App 端则面临后台保活失败、系统杀进程后消息丢失等问题。真实项目中:
– 微信小程序必须用 TXIM 或 融云 小程序版 SDK;
– App 端必须集成对应平台的原生插件(如 nativeplugins/zego-zim);
– H5 端可降级为长轮询 + uni.setStorageSync 本地缓存,但无离线推送。
scroll-view 滚动到底部失效的常见原因
很多人用 :scroll-top="scrollTop" 手动控制滚动,却始终卡在中间——根本原因是:
– 消息列表 DOM 渲染未完成时就执行了 uni.createSelectorQuery();
– scroll-view 的 scroll-y 未设固定高度(父容器没给 height 或 max-height);
– 新增消息后未触发 $nextTick 再调用 scrollTo;
– 使用了 scroll-into-view 但目标元素 ID 动态生成(如 :id="'msg'+index")而 index 变化后 ID 重复或未挂载。
实操建议:
– 给 scroll-view 加 :style="{ height: contentHeight + 'px' }"(contentHeight 需监听窗口变化);
– 滚动到底部统一走 this.$nextTick(() => { this.scrollTop = 999999 });
– 避免在 v-for 中用计算属性生成 ID,改用稳定唯一字段如 :id="'msg-'+msg.id"。
一站式排查小程序隐私授权报错(errno 104 / buttonId is wrong 等)+ 标准修改模式。适用:隐私协议配置、隐私弹窗不弹、授权报错、隐私接口调用失败。已抽离具体项目,适用于任何微信小程序。
键盘弹起时输入框被遮挡,adjust-position 失效怎么办?
input 组件的 adjust-position 在 iOS 和部分安卓机型上不可靠,尤其当页面用了自定义导航栏或 scroll-view 嵌套时。更稳的方案是:
– 监听 uni.onKeyboardHeightChange 获取实时键盘高度;
– 用 :style="{ bottom: keyboardHeight + 'px' }" 动态调整输入区位置;
– 同时设置 input 的 cursor-spacing(推荐 50–80)避免光标被遮;
– H5 端需额外判断 uni.getSystemInfoSync().platform === 'h5',改用 window.scrollTo(0, document.body.scrollHeight) 强制滚动。
注意:keyboardHeight 在某些安卓厂商系统(如华为 EMUI)中首次触发为 0,需加防抖并 fallback 到默认值(如 200)。
表情/图片/语音消息的跨端兼容要点
不同端对媒体文件处理差异极大:
– 表情:GIF 动图在小程序中需转为 base64 或 CDN 地址,image 组件不支持本地 static 路径下的 GIF;
– 图片:App 端可用 uni.chooseImage({ sourceType: ['album', 'camera'] }),但小程序需加 sizeType: ['compressed'] 防止超 2MB 限制;
– 语音:H5 无录音 API,必须用 uni-app 插件(如 uni-record);小程序用 uni.startRecord 已废弃,须用 uni.getRecorderManager;
– 预览:图片用 uni.previewImage 安全,但语音/视频需自己封装播放器组件,避免直接用 video 标签导致小程序真机不播。
uni.$emit)+ Pinia 持久化三者配合,缺一不可。


















