fix: 修复票据页面实机滚动卡死问题
问题描述: - iOS/Android 实机测试时,票据页面下滑后无法上滑 - 必须切换 Tab Bar 才能恢复 根本原因: - 页面容器未限制高度,Webview 弹性滚动与 scroll-view 手势冲突 - 页面级下拉刷新与 scroll-view 刷新机制并存,增加手势复杂度 修复方案: - pages.json: 禁用页面级下拉刷新,开启 disableScroll - ticket-wallet.css: 容器高度改为 100vh + overflow:hidden,滚动区高度简化为 100% 关联文档: - docs/troubleshoot-ticket-wallet-scroll.mdmaster
parent
02adc5f1c5
commit
6e80f6e9a6
|
|
@ -0,0 +1,125 @@
|
|||
# 票据页面滚动卡死问题排查与修复
|
||||
|
||||
> **问题编号**: #0004
|
||||
> **问题类型**: 移动端实机交互异常
|
||||
> **影响页面**: `pages/plugins/vr-ticket-wallet/ticket-wallet`(我的票夹)
|
||||
> **发现日期**: 2026-06-25
|
||||
> **修复状态**: ✅ 已修复并提交
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题描述
|
||||
|
||||
在实机测试环境下(iOS/Android H5 或微信 Webview),用户进入「我的票夹」页面后,一旦页面发生下滑,之后往往**无法继续上滑操作**,必须通过底部 Tab Bar 切换到其他视图页面后,才能恢复正常滚动。
|
||||
|
||||
---
|
||||
|
||||
## 2. 问题原因分析
|
||||
|
||||
### 2.1 滚动容器层级冲突
|
||||
|
||||
票据页面采用了自定义导航栏(`navigationStyle: custom`),使用 `<scroll-view>` 组件来实现页面内部滚动。问题根源在于**页面容器与 `<scroll-view>` 的滚动边界未被正确约束**,导致在移动端实机的 Webview 中:
|
||||
|
||||
- 系统级 Webview 的弹性滚动(bounce scroll)与 `<scroll-view>` 内部滚动产生**手势冲突**
|
||||
- 当用户下滑至内容底部后,系统 Webview 的弹性滚动接管了手势,但 `<scroll-view>` 的 `scroll-y` 并未释放
|
||||
- 再次上滑时,手势被系统拦截,导致**页面无法响应**
|
||||
|
||||
### 2.2 容器高度未限制
|
||||
|
||||
原代码中根容器 `.ticket-wallet-page` 使用了 `min-height: 100vh`,且未设置 `overflow: hidden`,使得容器可以超出视口高度,产生滚动空间,与内部 `<scroll-view>` 的滚动区域重叠。
|
||||
|
||||
### 2.3 下拉刷新配置冲突
|
||||
|
||||
`pages.json` 中对 `ticket-wallet` 页面同时配置了:
|
||||
- `enablePullDownRefresh: true`(页面级下拉刷新)
|
||||
- `<scroll-view>` 组件内部的 `refresher-enabled: true`
|
||||
|
||||
两套下拉刷新机制并存,增加了手势处理的复杂度。
|
||||
|
||||
---
|
||||
|
||||
## 3. 修复方案
|
||||
|
||||
### 3.1 修改 `pages.json`
|
||||
|
||||
**文件**: `pages.json` 第 2232–2244 行
|
||||
|
||||
**改动**:
|
||||
```diff
|
||||
{
|
||||
"path": "ticket-wallet",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
- "enablePullDownRefresh": true,
|
||||
+ "enablePullDownRefresh": false,
|
||||
+ "disableScroll": true,
|
||||
"navigationBarTitleText": "",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **禁用页面级下拉刷新**(`enablePullDownRefresh: false`):避免页面级滚动与 `<scroll-view>` 冲突
|
||||
- **开启禁止页面滚动**(`disableScroll: true`):彻底禁止系统 Webview 的弹性滚动,将手势控制权完全交给 `<scroll-view>`
|
||||
|
||||
> [!NOTE]
|
||||
> 下拉刷新功能并未丢失——`<scroll-view>` 组件自身提供的 `refresher-enabled` 属性已接管下拉刷新逻辑,行为保持一致。
|
||||
|
||||
### 3.2 修改 `ticket-wallet.css`
|
||||
|
||||
**文件**: `pages/plugins/vr-ticket-wallet/ticket-wallet.css`
|
||||
|
||||
#### 改动一:根容器高度约束
|
||||
|
||||
```diff
|
||||
.ticket-wallet-page {
|
||||
- min-height: 100vh;
|
||||
+ height: 100vh;
|
||||
+ overflow: hidden;
|
||||
background: radial-gradient(circle at center, #fef4f4 0%, #f3e5e5 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
```
|
||||
|
||||
- 使用固定高度 `100vh` 替代 `min-height`,配合 `overflow: hidden` 确保容器不会超出视口
|
||||
|
||||
#### 改动二:滚动区域高度简化
|
||||
|
||||
```diff
|
||||
.wallet-scroll {
|
||||
flex: 1;
|
||||
- height: calc(100vh - 88rpx);
|
||||
+ height: 100%;
|
||||
}
|
||||
```
|
||||
|
||||
- 移除硬编码的高度计算(`88rpx` 对应被注释掉的顶部导航栏高度)
|
||||
- 使用 `height: 100%` 让滚动区域自适应父容器
|
||||
|
||||
---
|
||||
|
||||
## 4. 验证方法
|
||||
|
||||
1. 在 iOS Safari 或微信开发者工具中打开「我的票夹」页面
|
||||
2. 持续向下滑动至内容底部
|
||||
3. 尝试上滑——页面应能流畅响应,不会出现卡死现象
|
||||
4. 执行下拉刷新——`<scroll-view>` 自带的刷新指示器应正常触发
|
||||
5. 切换 Tab Bar 至其他页面后返回——滚动状态应正常保留
|
||||
|
||||
---
|
||||
|
||||
## 5. 相关文件
|
||||
|
||||
| 文件 | 改动类型 |
|
||||
|------|----------|
|
||||
| `pages.json` | 修改 |
|
||||
| `pages/plugins/vr-ticket-wallet/ticket-wallet.css` | 修改 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 预防措施
|
||||
|
||||
- 在使用自定义 `<scroll-view>` 作为主要滚动容器的页面中,统一添加 `"disableScroll": true` 到 `pages.json`
|
||||
- 确保根容器使用 `height: 100vh` + `overflow: hidden` 约束,避免与 Webview 滚动冲突
|
||||
- 避免在同一页面中混用页面级下拉刷新与 `<scroll-view>` 下拉刷新
|
||||
|
|
@ -2233,7 +2233,8 @@
|
|||
"path": "ticket-wallet",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": true,
|
||||
"enablePullDownRefresh": false,
|
||||
"disableScroll": true,
|
||||
"navigationBarTitleText": "",
|
||||
"usingComponents": {
|
||||
"u-popup": "/components/u-popup/u-popup",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* ========== 页面整体布局 ========== */
|
||||
.ticket-wallet-page {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background: radial-gradient(circle at center, #fef4f4 0%, #f3e5e5 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -68,16 +69,9 @@
|
|||
/* ========== 主滚动区域 ========== */
|
||||
.wallet-scroll {
|
||||
flex: 1;
|
||||
height: calc(100vh - 88rpx);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* #ifdef MP-WEIXIN || MP-BAIDU || MP-QQ || MP-KUAISHOU || H5 || APP */
|
||||
.wallet-scroll {
|
||||
height: calc(100vh - 88rpx - constant(safe-area-inset-top));
|
||||
height: calc(100vh - 88rpx - env(safe-area-inset-top));
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
/* ========== 顶部潮流 Banner ========== */
|
||||
.brand-banner {
|
||||
position: relative;
|
||||
|
|
|
|||
Loading…
Reference in New Issue