必须用v-if+,因uni.showmodal等原生弹窗不走vue渲染流程,无法触发css动画;需手写组件并显式设置transform-origin:center、避免scale(0)、禁用will-change,且pages.json中须关闭enablepulldownrefresh。

uni-app 自定义下拉面板必须用 v-if + <transition></transition>
直接调用 uni.showModal 或 uni.showToast 无法触发任何 CSS 动画,它们走的是原生弹窗通道,不经过 Vue 渲染流程。想缩放+位移,只能手写组件,用 v-if 控制显隐,并包裹在 <transition name="pull-panel"></transition> 中。
常见错误是:v-show 搭配 <transition></transition> —— 它不会触发 enter/leave 钩子,动画压根不执行。
-
<transition></transition>必须带name属性(如name="pull-panel"),否则类名默认为v-enter,易与其他组件冲突 - 对应 CSS 要写全三阶段:
.pull-panel-enter-active、.pull-panel-enter-from、.pull-panel-enter-to,缺一不可 - 动画时长(如
0.25s)必须和 CSS 中transition-duration严格一致,否则leave-to阶段可能被跳过
缩放动画要设 transform-origin 且避免 scale(0)
小程序真机上缩放中心点错位、弹窗“飘走”,几乎全是 transform-origin 没显式声明导致的。微信/支付宝默认按左上角缩放,而 H5 默认居中,同一套代码在不同平台表现完全不同。
- 统一写成
transform-origin: center或transform-origin: 50% 50%,别依赖默认值 - 安卓低端机上
scale(0)可能让元素彻底消失且无法恢复,建议最小值用scale(0.01) - 缩放必须搭配
translateY()实现“从顶部下拉展开”效果,例如:transform: scale(0.95) translateY(-40px) - 禁用
will-change: transform,uni-app 自身已做优化,手动加反而引发重绘异常
App 端下拉刷新和自定义面板不能混用
页面根容器一旦开启 "enablePullDownRefresh": true,原生下拉手势就会接管整个 page,你写的自定义下拉面板会被拦截或失效——尤其在 iOS 上,手指稍一拉就会触发原生刷新,根本碰不到你的面板。
- 若要自定义下拉面板,
pages.json中对应页面必须设"enablePullDownRefresh": false - 监听
@touchstart/@touchmove/@touchend手动判断下拉距离,而非依赖onPullDownRefresh - Android 部分机型(如华为 EMUI)会拦截
scroll-view的触顶事件,需配合bounce="true"和refresher-enabled="false"使用 - 松手后是否触发逻辑,取决于
deltaY > 60这类阈值判断,不是靠原生刷新机制
scroll-view 内嵌自定义下拉需关掉 overflow: hidden
把自定义下拉面板放在 <scroll-view></scroll-view> 里时,如果父容器设置了 overflow: hidden,缩放过程会被裁剪,出现闪烁、错位甚至动画卡死。
- 去掉父级
overflow: hidden,改用clip-path或mask控制可视区域更安全 -
<scroll-view></scroll-view>必须设refresher-enabled="false",否则会和你的 touch 事件冲突 - 真机测试时重点看 iOS:
bounce="true"必须开启,否则触顶无物理反馈,用户感知不到“可下拉” - 缩放对象含图片时,务必固定
width/height,否则缩放引发 layout 波动,动画抖动明显
transform-origin 对齐,没别的取巧办法。










