7.4 KiB
7.4 KiB
放弃弹窗组件化改进说明
更新日期:2026-03-14 改进内容:创建可复用的放弃弹窗组件,修复首次输入不触发交互的问题
问题分析
原问题
- 首次输入不触发交互:任务列表页的放弃弹窗,首次点击 textarea 时不会触发键盘弹出事件
- 代码重复:任务列表页和任务详情页都有独立的放弃弹窗实现,代码重复
问题原因
原放弃弹窗的 overlay 层使用了 bindtap="onCloseAbandonModal",导致点击事件冒泡问题:
<view class="abandon-overlay" bindtap="onCloseAbandonModal">
<view class="abandon-modal" catchtap="noop">
<textarea ... />
</view>
</view>
当首次点击 textarea 时,事件可能被 overlay 的 bindtap 干扰,导致 textarea 的 focus 事件不能正常触发。
解决方案
1. 创建可复用的放弃弹窗组件
组件路径:components/abandon-modal/
组件特点:
- 完整的键盘交互支持
- 自动验证输入内容
- 统一的样式和交互
- 可在多个页面复用
组件文件:
abandon-modal.wxml- 模板abandon-modal.ts- 逻辑abandon-modal.wxss- 样式abandon-modal.json- 配置
2. 修复事件冒泡问题
改进前:
<view class="abandon-overlay" bindtap="onCloseAbandonModal">
改进后:
<view class="modal-overlay" catchtap="onCancel" catchtouchmove="noop">
关键改进:
- 使用
catchtap替代bindtap,阻止事件冒泡 - 添加
catchtouchmove="noop"防止滚动穿透 - 内部容器使用
catchtap="noop"阻止点击关闭
组件使用方法
在页面中注册组件
JSON 配置:
{
"usingComponents": {
"abandon-modal": "/components/abandon-modal/abandon-modal"
}
}
在页面中使用组件
WXML:
<abandon-modal
visible="{{abandonModalVisible}}"
customerName="{{customerName}}"
bind:confirm="onAbandonConfirm"
bind:cancel="onAbandonCancel"
/>
事件处理
TypeScript:
// 打开弹窗
onOpenAbandon() {
this.setData({ abandonModalVisible: true })
}
// 确认放弃
onAbandonConfirm(e: WechatMiniprogram.CustomEvent<{ reason: string }>) {
const { reason } = e.detail
// 处理放弃逻辑
this.setData({ abandonModalVisible: false })
}
// 取消
onAbandonCancel() {
this.setData({ abandonModalVisible: false })
}
组件属性
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| visible | Boolean | 是 | 是否显示弹窗 |
| customerName | String | 是 | 客户名称 |
组件事件
| 事件名 | 参数 | 说明 |
|---|---|---|
| confirm | { reason: string } | 确认放弃,返回放弃原因 |
| cancel | - | 取消操作 |
页面改进
任务列表页
改进内容:
- 移除内联放弃弹窗代码
- 使用
abandon-modal组件 - 简化事件处理逻辑
- 移除不需要的 data 字段(abandonReason, abandonError, keyboardHeight)
改进文件:
pages/task-list/task-list.wxmlpages/task-list/task-list.tspages/task-list/task-list.json
任务详情页
改进内容:
- 移除内联放弃弹窗代码
- 使用
abandon-modal组件 - 简化事件处理逻辑
- 移除不需要的 data 字段和方法
改进文件:
pages/task-detail/task-detail.wxmlpages/task-detail/task-detail.tspages/task-detail/task-detail.json
技术细节
1. 事件冒泡控制
关键点:
- overlay 使用
catchtap阻止事件冒泡 - 内部容器使用
catchtap="noop"防止关闭 - textarea 的 focus/blur 事件正常触发
2. 键盘交互
实现方式:
// 键盘弹出
onTextareaFocus(e: WechatMiniprogram.InputEvent) {
const height = (e as any).detail?.height ?? 0
this.setData({ keyboardHeight: height })
}
// 键盘收起
onTextareaBlur() {
this.setData({ keyboardHeight: 0 })
}
样式适配:
/* 键盘弹出时,弹窗移到顶部 */
.modal-overlay--keyboard-open {
align-items: flex-start;
}
/* 按钮固定在键盘上方 */
.modal-footer--float {
position: fixed;
bottom: [keyboardHeight]px;
}
3. 输入验证
自动验证:
observers: {
content(val: string) {
this.setData({
canSave: val.trim().length > 0,
})
},
}
提交验证:
onConfirm() {
if (!this.data.canSave) {
this.setData({ error: true })
return
}
// 触发确认事件
}
代码对比
改进前(任务列表页)
WXML(约40行):
<view class="abandon-overlay" wx:if="{{abandonModalVisible}}" bindtap="onCloseAbandonModal">
<view class="abandon-modal" catchtap="noop">
<!-- 大量内联代码 -->
</view>
</view>
TypeScript(约50行):
data: {
abandonReason: '',
abandonError: false,
keyboardHeight: 0,
},
onAbandonInput() { ... }
onAbandonTextareaFocus() { ... }
onAbandonTextareaBlur() { ... }
onAbandonConfirm() { ... }
onCloseAbandonModal() { ... }
改进后(任务列表页)
WXML(5行):
<abandon-modal
visible="{{abandonModalVisible}}"
customerName="{{abandonTarget.customerName}}"
bind:confirm="onAbandonConfirm"
bind:cancel="onAbandonCancel"
/>
TypeScript(约15行):
onAbandonConfirm(e: WechatMiniprogram.CustomEvent<{ reason: string }>) {
const { reason } = e.detail
// 处理逻辑
}
onAbandonCancel() {
this.setData({ abandonModalVisible: false })
}
代码减少:约70行 → 约20行(减少70%)
测试验证
功能测试
- 首次点击 textarea 正常触发键盘弹出
- 键盘弹出时弹窗自动上移
- 按钮固定在键盘上方
- 输入框获得焦点时边框变蓝
- 空内容时显示错误提示
- 确认后正确返回放弃原因
- 取消后正确关闭弹窗
兼容性测试
- 任务列表页使用正常
- 任务详情页使用正常
- 两个页面交互一致
性能测试
- 组件加载速度正常
- 键盘弹出流畅
- 无内存泄漏
优势总结
1. 代码复用
- 一次编写,多处使用
- 减少代码重复
- 降低维护成本
2. 问题修复
- 修复首次输入不触发交互的问题
- 统一事件处理逻辑
- 改善用户体验
3. 易于维护
- 组件化设计
- 清晰的接口定义
- 完整的文档说明
4. 扩展性强
- 可轻松添加新功能
- 可在其他页面复用
- 可根据需求定制
后续优化建议
- 添加动画效果:弹窗打开/关闭时的过渡动画
- 支持自定义标题:允许传入自定义标题文本
- 支持自定义按钮文本:允许自定义确认/取消按钮文本
- 添加最大长度提示:显示剩余可输入字符数
- 支持多行输入优化:自动调整 textarea 高度
相关文件清单
新增文件
components/abandon-modal/abandon-modal.wxmlcomponents/abandon-modal/abandon-modal.tscomponents/abandon-modal/abandon-modal.wxsscomponents/abandon-modal/abandon-modal.json
修改文件
pages/task-list/task-list.wxmlpages/task-list/task-list.tspages/task-list/task-list.jsonpages/task-detail/task-detail.wxmlpages/task-detail/task-detail.tspages/task-detail/task-detail.json
文档维护者:AI Assistant
最后更新:2026-03-14