如何为JS Modal类实现独立的onClose与onSubmit回调函数?
实现支持独立处理onClose/onSubmit事件的Modal类
需求
要创建一个Modal类,支持两种使用方式:
- 链式调用绑定回调
new Modal().setTitle('Some title') .onClose(function(form, modal) { }) .onSubmit(function(form, modal) { });
- 直接赋值回调函数
const modal = new Modal().setTitle('Some title'); modal.onClose = function(form, modal) { }; modal.onSubmit = function(form, modal) { };
当前代码问题
现有Modal类代码如下:
class Modal { #btnClose; #btnConfirm; #modal; #form; constructor() { const self = this; this.#btnClose = document.getElementById('btn-close'); this.#btnConfirm = document.getElementById('btn-confirm'); this.#form = document.getElementById('form'); this.#modal = new bootstrap.Modal(document.getElementById('modal'), {}); this.#modal.toggle(); this.#btnClose.onclick = function() { self.#_onClose(self); } } #_onClose(self) { // 默认行为 self.#modal.toggle(); // 应调用onClose()函数 self.onClose(() => (self.#form, self.#modal)); } onClose(callback) { callback(this.#form, this.#modal); return this; } }
存在两个问题:
- 点击「打开模态框」按钮后,
onClose()函数立即被调用 - 点击「关闭」按钮后,
onClose()函数从未触发
修复方案
核心问题是没存储回调函数,而是直接在onClose方法里执行了传入的回调,同时关闭按钮的触发逻辑错误。按以下步骤修改:
1. 新增私有变量存储回调
在类里添加两个私有属性,分别保存onClose和onSubmit的回调:
#onCloseCallback = null; #onSubmitCallback = null;
2. 修改onClose和新增onSubmit链式方法
这两个方法只负责存储回调,不立即执行,返回this支持链式调用:
onClose(callback) { this.#onCloseCallback = callback; return this; } onSubmit(callback) { this.#onSubmitCallback = callback; return this; }
3. 支持直接赋值回调的getter/setter
为了兼容直接赋值modal.onClose = ...的方式,添加对应的getter和setter:
get onClose() { return this.#onCloseCallback; } set onClose(callback) { this.#onCloseCallback = callback; } get onSubmit() { return this.#onSubmitCallback; } set onSubmit(callback) { this.#onSubmitCallback = callback; }
4. 修复关闭按钮的触发逻辑
在#_onClose方法里,先执行默认关闭行为,再判断如果有回调就调用它,传入正确参数:
#_onClose() { // 默认行为:关闭模态框,用bootstrap的hide比toggle更可靠 this.#modal.hide(); // 存在回调则执行 if (typeof this.#onCloseCallback === 'function') { this.#onCloseCallback(this.#form, this.#modal); } }
构造函数里的按钮绑定改用箭头函数,不用传self:
this.#btnClose.onclick = () => { this.#_onClose(); };
5. 补充onSubmit的逻辑(同理)
给确认按钮绑定点击事件,触发#_onSubmit方法:
// 构造函数内添加 this.#btnConfirm.onclick = () => { this.#_onSubmit(); }; // 新增私有提交方法 #_onSubmit() { // 可选:先做表单验证 const isValid = this.#form.checkValidity(); if (!isValid) { this.#form.reportValidity(); return; } // 存在回调则执行 if (typeof this.#onSubmitCallback === 'function') { this.#onSubmitCallback(this.#form, this.#modal); } }
完整修正后的代码
class Modal { #btnClose; #btnConfirm; #modal; #form; #onCloseCallback = null; #onSubmitCallback = null; constructor() { this.#btnClose = document.getElementById('btn-close'); this.#btnConfirm = document.getElementById('btn-confirm'); this.#form = document.getElementById('form'); this.#modal = new bootstrap.Modal(document.getElementById('modal'), {}); // 绑定按钮事件 this.#btnClose.onclick = () => this.#_onClose(); this.#btnConfirm.onclick = () => this.#_onSubmit(); // 打开模态框,用show替代toggle避免状态问题 this.#modal.show(); } // 链式调用方法 onClose(callback) { this.#onCloseCallback = callback; return this; } onSubmit(callback) { this.#onSubmitCallback = callback; return this; } // 支持直接赋值的getter/setter get onClose() { return this.#onCloseCallback; } set onClose(callback) { this.#onCloseCallback = callback; } get onSubmit() { return this.#onSubmitCallback; } set onSubmit(callback) { this.#onSubmitCallback = callback; } // 私有关闭逻辑 #_onClose() { this.#modal.hide(); if (typeof this.#onCloseCallback === 'function') { this.#onCloseCallback(this.#form, this.#modal); } } // 私有提交逻辑 #_onSubmit() { // 表单验证(可选,按需调整) const isValid = this.#form.checkValidity(); if (!isValid) { this.#form.reportValidity(); return; } if (typeof this.#onSubmitCallback === 'function') { this.#onSubmitCallback(this.#form, this.#modal); } } // 补充需求里提到的setTitle方法 setTitle(title) { const modalTitle = document.getElementById('modal-title'); if (modalTitle) { modalTitle.textContent = title; } return this; } }
验证两种使用方式
链式调用:
new Modal().setTitle('编辑用户') .onClose((form, modal) => { console.log('模态框关闭了', form, modal); }) .onSubmit((form, modal) => { console.log('提交表单', new FormData(form)); modal.hide(); // 提交后手动关闭 });
直接赋值:
const modal = new Modal().setTitle('新增内容'); modal.onClose = (form, modal) => { alert('你关闭了模态框'); }; modal.onSubmit = (form, modal) => { // 处理提交逻辑 console.log('提交数据'); };
内容的提问来源于stack exchange,提问作者Linesofcode
相关产品推荐
相关产品推荐

