// 模态框管理器 class ModalManager { constructor() { // 模态框类型注册表 this.modalTypes = { 'createOrder': { name: '创建订单', template: 'createOrderModal' }, 'addProduct': { name: '添加产品', template: 'addProductModal' }, 'editProduct': { name: '编辑产品', template: 'editProductModal' }, 'addComponent': { name: '添加组件', template: 'addComponentModal' }, 'addBancai': { name: '添加板材', template: 'addBancaiModal' }, 'bancaiDetail': { name: '板材详情', template: 'bancaiDetailModal' }, 'stockEdit': { name: '库存编辑', template: 'stockEditModal' }, 'materialDetail': { name: '材料详情', template: 'materialDetailModal' } }; // 模态框堆栈 this.modalStack = []; // 默认配置 this.defaultConfig = { title: '提示', content: '', buttons: [ { text: '取消', type: 'cancel', style: 'default' }, { text: '确定', type: 'confirm', style: 'primary' } ], maskClosable: true, zIndex: 1000, animation: true, customClass: '' }; } // 注册新的模态框类型 registerModalType(type, config) { this.modalTypes[type] = config; } // 显示模态框 showModal(pageContext, type, data = {}, config = {}) { // 合并配置 const modalConfig = { ...this.defaultConfig, ...config }; // 检查模态框类型 const modalType = this.modalTypes[type]; if (!modalType) { console.error(`未注册的模态框类型: ${type}`); return; } // 创建模态框对象 const modal = { id: Date.now(), // 唯一ID type, template: modalType.template, data: { ...data, ...modalConfig }, pageContext, zIndex: modalConfig.zIndex + this.modalStack.length * 10 }; // 添加到堆栈 this.modalStack.push(modal); // 更新页面数据 this.updatePageModals(pageContext); return modal.id; } // 关闭模态框 closeModal(pageContext, id, result = null) { const index = this.modalStack.findIndex(m => m.id === id); if (index !== -1) { const modal = this.modalStack.splice(index, 1)[0]; // 如果有回调函数,执行回调 if (modal.data.onClose) { modal.data.onClose(result); } // 更新页面 this.updatePageModals(pageContext); return true; } return false; } // 关闭所有模态框 closeAllModals(pageContext) { if (this.modalStack.length > 0) { this.modalStack = []; this.updatePageModals(pageContext); } } // 处理按钮点击 handleButtonClick(pageContext, id, buttonType) { const modal = this.modalStack.find(m => m.id === id); if (!modal) return; // 查找按钮配置 const buttonConfig = modal.data.buttons.find(b => b.type === buttonType); if (buttonConfig && buttonConfig.handler) { // 执行按钮处理函数 buttonConfig.handler({ modalId: id, modalType: modal.type, modalData: modal.data, close: (result) => this.closeModal(pageContext, id, result) }); } else if (buttonType === 'cancel') { // 默认取消行为 this.closeModal(pageContext, id); } } // 更新页面模态框数据 updatePageModals(pageContext) { if (!pageContext) return; // 获取当前页面可见的模态框 const visibleModals = this.modalStack.filter(modal => modal.pageContext === pageContext ); // 设置页面数据 pageContext.setData({ modals: visibleModals.map(modal => ({ id: modal.id, type: modal.type, template: modal.template, data: modal.data, zIndex: modal.zIndex })) }); } } // 创建单例 const modalManager = new ModalManager(); // 导出模块 module.exports = modalManager; 嵌套模态框中的数据在关闭时刷新父级模态框数据
时间: 2025-07-20 10:30:55 浏览: 11
<think>为了在嵌套模态框中实现关闭子模态框时刷新父级模态框数据,我们需要在ModalManager中添加父子模态框关系的管理,并在子模态框关闭时触发父级模态框的刷新回调。以下是改进后的ModalManager代码:
改进点:
1. 在显示模态框时记录父子关系(当前打开的模态框作为父模态框,新打开的模态框作为子模态框)。
2. 为每个模态框增加一个`onChildClosed`回调函数,当子模态框关闭时,父模态框可以通过这个回调函数刷新数据。
3. 在关闭模态框时,检查是否有父模态框注册了`onChildClosed`回调,如果有则执行。
注意:为了避免内存泄漏,当父模态框关闭时,需要清理其与子模态框的关联。
以下是修改后的代码:</think># 嵌套模态框数据刷新机制:关闭子模态框时刷新父级模态框数据
下面我将提供一个完整的解决方案,在现有 `ModalManager` 类的基础上添加父子模态框关系管理,并在子模态框关闭时刷新父级模态框数据。
## 改进后的 ModalManager 类
```javascript:utils/modal-manager.js
// 增强版模态框管理器
class ModalManager {
constructor() {
// 模态框类型注册表
this.modalTypes = {
'createOrder': { name: '创建订单', template: 'createOrderModal' },
'addProduct': { name: '添加产品', template: 'addProductModal' },
'editProduct': { name: '编辑产品', template: 'editProductModal' },
'addComponent': { name: '添加组件', template: 'addComponentModal' },
'addBancai': { name: '添加板材', template: 'addBancaiModal' },
'bancaiDetail': { name: '板材详情', template: 'bancaiDetailModal' },
'stockEdit': { name: '库存编辑', template: 'stockEditModal' },
'materialDetail': { name: '材料详情', template: 'materialDetailModal' }
};
// 模态框堆栈
this.modalStack = [];
// 默认配置
this.defaultConfig = {
title: '提示',
content: '',
buttons: [
{ text: '取消', type: 'cancel', style: 'default' },
{ text: '确定', type: 'confirm', style: 'primary' }
],
maskClosable: true,
zIndex: 1000,
animation: true,
customClass: ''
};
// 父子关系映射表 {子模态框ID: 父模态框ID}
this.parentChildMap = new Map();
}
// 注册新的模态框类型
registerModalType(type, config) {
this.modalTypes[type] = config;
}
// 显示模态框
showModal(pageContext, type, data = {}, config = {}) {
// 合并配置
const modalConfig = { ...this.defaultConfig, ...config };
// 检查模态框类型
const modalType = this.modalTypes[type];
if (!modalType) {
console.error(`未注册的模态框类型: ${type}`);
return;
}
// 创建模态框对象
const modal = {
id: Date.now(), // 唯一ID
type,
template: modalType.template,
data: { ...data, ...modalConfig },
pageContext,
zIndex: modalConfig.zIndex + this.modalStack.length * 10
};
// 记录父子关系
if (this.modalStack.length > 0) {
const parentModal = this.modalStack[this.modalStack.length - 1];
this.parentChildMap.set(modal.id, parentModal.id);
}
// 添加到堆栈
this.modalStack.push(modal);
// 更新页面数据
this.updatePageModals(pageContext);
return modal.id;
}
// 关闭模态框
closeModal(pageContext, id, result = null) {
const index = this.modalStack.findIndex(m => m.id === id);
if (index !== -1) {
const modal = this.modalStack.splice(index, 1)[0];
// 触发父级刷新
this.triggerParentRefresh(id, result);
// 清理父子关系
this.cleanupParentChildRelations(id);
// 如果有回调函数,执行回调
if (modal.data.onClose) {
modal.data.onClose(result);
}
// 更新页面
this.updatePageModals(pageContext);
return true;
}
return false;
}
// 触发父级刷新
triggerParentRefresh(childId, result) {
const parentId = this.parentChildMap.get(childId);
if (!parentId) return;
// 查找父级模态框
const parentModal = this.modalStack.find(m => m.id === parentId);
if (parentModal && parentModal.data.onChildClosed) {
// 执行父级的子模态框关闭回调
parentModal.data.onChildClosed(result);
// 更新父级模态框的数据
this.updateModalData(parentModal, {
refreshed: true,
refreshTime: new Date().toLocaleTimeString()
});
}
}
// 更新模态框数据
updateModalData(modal, newData) {
Object.assign(modal.data, newData);
// 更新页面
const dataUpdate = {};
dataUpdate[this.modalTypes[modal.type].name] = modal.data;
modal.pageContext.setData(dataUpdate);
}
// 清理父子关系
cleanupParentChildRelations(modalId) {
// 清理作为父级的关系
for (const [childId, parentId] of this.parentChildMap) {
if (parentId === modalId) {
this.parentChildMap.delete(childId);
}
}
// 清理作为子级的关系
this.parentChildMap.delete(modalId);
}
// 其他方法保持不变...
// ...(handleButtonClick, updatePageModals等方法)
}
// 创建单例
const modalManager = new ModalManager();
// 导出模块
module.exports = modalManager;
```
## 使用示例
### 在父级模态框中注册子模态框关闭回调
```javascript:pages/dingdan/dingdan.js
const app = getApp();
Page({
data: {
modals: []
},
// 打开父级模态框
openParentModal() {
const parentModalId = app.modalManager.showModal(this, 'createOrder', {
title: '创建订单',
orderNumber: `DD${Date.now()}`,
products: [],
// 注册子模态框关闭回调
onChildClosed: (result) => {
if (result && result.success) {
console.log('子模态框关闭,刷新父级数据', result);
// 更新父级模态框数据
const newProducts = [...this.data.products, result.newProduct];
app.modalManager.updateModalData(parentModalId, {
products: newProducts,
lastRefresh: new Date().toLocaleTimeString()
});
}
}
});
// 保存父级模态框ID
this.parentModalId = parentModalId;
},
// 在父级模态框中打开子模态框
onAddProductButtonTap() {
const childModalId = app.modalManager.showModal(this, 'addProduct', {
title: '添加产品',
product: {
name: '',
quantity: 1
}
});
// 保存子模态框ID
this.childModalId = childModalId;
},
// 在子模态框中保存数据并关闭
onSaveProduct() {
// 保存逻辑...
const result = {
success: true,
newProduct: this.data.product
};
// 关闭当前模态框并传递结果
app.modalManager.closeModal(this, this.childModalId, result);
}
});
```
### 在 WXML 中传递模态框 ID
```wxml:components/modals/templates/createOrderModal.wxml
<template name="createOrderModal">
<view class="modal">
<view class="modal-header">{{data.title}}</view>
<view class="modal-body">
<!-- 订单信息 -->
<view>订单号: {{data.orderNumber}}</view>
<!-- 产品列表 -->
<view class="section-title">产品列表</view>
<block wx:for="{{data.products}}" wx:key="id">
<view class="product-item">
{{item.name}} - {{item.quantity}}件
</view>
</block>
<!-- 刷新状态 -->
<view wx:if="{{data.refreshed}}" class="refresh-indicator">
数据刷新于: {{data.refreshTime}}
</view>
</view>
<view class="modal-footer">
<!-- 添加产品按钮 -->
<view
class="modal-button button-primary"
bindtap="onAddProductButtonTap"
data-modal-id="{{modalId}}"
>
添加产品
</view>
<!-- 关闭按钮 -->
<view
class="modal-button button-default"
bindtap="onModalButtonTap"
data-type="cancel"
data-modal-id="{{modalId}}"
>
关闭
</view>
</view>
</view>
</template>
```
## 解决方案说明
### 核心机制
1. **父子关系管理**:
- 使用 `parentChildMap` 记录模态框的父子关系
- 当打开子模态框时,自动记录它与当前顶部模态框(父级)的关系
2. **关闭时触发父级刷新**:
- 在关闭子模态框时,检查是否有父级模态框
- 如果有父级且父级注册了 `onChildClosed` 回调,则执行该回调
3. **父级数据更新**:
- 在回调中更新父级模态框的数据
- 使用 `updateModalData` 方法更新父级模态框的显示
4. **关系清理**:
- 模态框关闭时自动清理父子关系
- 防止内存泄漏和无效引用
### 使用场景
1. **添加产品后刷新订单**:
- 在订单创建模态框中添加产品
- 产品添加模态框关闭后刷新订单中的产品列表
2. **编辑库存后刷新概览**:
- 在库存概览模态框中编辑具体库存项
- 库存编辑模态框关闭后刷新概览数据
3. **创建组件后刷新产品配置**:
- 在产品配置模态框中添加新组件
- 组件创建模态框关闭后刷新产品配置
### 优势
1. **解耦设计**:父级和子级模态框不需要直接引用对方
2. **自动关系管理**:父子关系由 ModalManager 自动管理
3. **灵活刷新**:可以根据需要决定刷新哪些数据
4. **状态反馈**:在父级模态框中显示刷新状态
5. **资源安全**:自动清理关系,防止内存泄漏
## 完整示例:添加产品到订单
```javascript:pages/dingdan/dingdan.js
const app = getApp();
Page({
data: {
modals: [],
currentOrder: null
},
// 创建新订单
createNewOrder() {
const order = {
id: `order_${Date.now()}`,
number: `DD${new Date().getTime()}`,
products: [],
status: 'draft'
};
this.setData({ currentOrder: order });
// 打开订单模态框
const modalId = app.modalManager.showModal(this, 'createOrder', {
title: '创建新订单',
order: order,
// 子模态框关闭回调
onChildClosed: (result) => {
if (result && result.success) {
// 更新产品列表
const newProducts = [...order.products, result.product];
order.products = newProducts;
// 更新模态框数据
app.modalManager.updateModalData(modalId, {
products: newProducts,
lastRefresh: new Date().toLocaleTimeString()
});
// 显示成功提示
wx.showToast({
title: '产品添加成功',
icon: 'success'
});
}
}
});
this.orderModalId = modalId;
},
// 添加产品到当前订单
addProductToOrder() {
const modalId = app.modalManager.showModal(this, 'addProduct', {
title: '添加产品',
product: {
id: `product_${Date.now()}`,
name: '',
quantity: 1,
price: 0
}
});
this.productModalId = modalId;
},
// 保存产品并关闭模态框
saveProduct() {
const product = this.data.product;
// 验证产品数据
if (!product.name || product.quantity <= 0) {
wx.showToast({
title: '请填写完整产品信息',
icon: 'none'
});
return;
}
// 关闭模态框并传递结果
app.modalManager.closeModal(this, this.productModalId, {
success: true,
product: product
});
},
// 处理模态框按钮点击
onModalButtonTap(e) {
const { type, modalId } = e.currentTarget.dataset;
app.modalManager.handleButtonClick(this, modalId, type);
}
});
```
##
阅读全文
相关推荐




















