最稳妥方案是用v-if控制dom卸载+max-height过渡动画,禁用v-show;多行截断用-webkit-box兼容各端;每条评论需独立展开状态管理。

uni-app里用v-if控制展开收起最稳妥
直接用v-show或手动改max-height做过渡,在微信/支付宝小程序里大概率会卡顿、闪动,甚至点击无响应。根本原因是v-show只切display,不触发真实 DOM 插入/销毁,导致滚动位置错乱、$nextTick时机不准、textarea聚焦失效等问题。
实操要点:
-
transition标签必须用name="fade"或name="slide",别自定义类名——H5 和小程序对enter-active-class解析不一致 - 初始状态设
isExpanded: false,点击只改这个布尔值,不要同时操作height或line-clamp - 展开区域必须用
<view v-if="isExpanded"></view>包裹,确保折叠后 DOM 彻底卸载 - 如果需要“展开后自动滚动到顶部”,在
this.$nextTick(() => uni.pageScrollTo(...))里调,否则节点还没渲染完成
多行文本截断得用-webkit-box方案
line-clamp在 H5 和 App 端能用,但在微信/支付宝小程序里基本无效——它们的 WebView 渲染层不支持-webkit-line-clamp,但display: -webkit-box是跨平台兼容的底线方案。
关键写法:
- 容器加
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; text-overflow: ellipsis; - 不能只靠 CSS 控制,得配合 JS 判断是否超长:用
uni.createSelectorQuery()查scrollHeight与clientHeight差值,再决定是否显示“展开”按钮 - 避免在
rich-text里直接套-webkit-box,它不支持该样式;应先用nodes转为纯文本或预处理 HTML
展开动画要用max-height过渡,不是height:auto
height: auto无法被transition捕获,浏览器不知道终点高度是多少。必须用max-height模拟,这是目前最轻量、无需 ref 计算、不依赖 JS 动画库的方案。
注意细节:
- 起始状态:
max-height: 0; overflow: hidden; - 展开目标值:设一个“明显大于内容实际高度”的固定值,比如
max-height: 500rpx(别用100vh,iOS Safari 会卡顿) - 收起后必须等
@transitionend或this.$nextTick后再把max-height切回0,否则下次展开可能闪一下 - 内容含图片或异步加载时,初始
max-height可能不够——优先给内容区设固定高度,或降级用transform: scaleY(0) → scaleY(1)
嵌套回复场景下,单条展开需独立状态管理
评论列表里每一条都可能被单独展开,不能共用一个isExpanded布尔值。否则点开第3条,第1条也会跟着展开。
正确做法是用对象映射管理状态:
- data 里定义
expandedItems: {},键为comment.id,值为true/false - 切换时用
this.$set(this.expandedItems, id, !this.expandedItems[id]),保证响应式更新 - 列表刷新后记得重置状态:
this.expandedItems = {},否则旧状态残留导致 UI 错乱 - 如果后端返回的是树状结构(带
tree_id和comment_id),展开某条评论时,建议连同其所有子回复一起展开,用递归判断更直观
v-if就完事,得把每个环节的时机和边界条件都对上。










