You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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;
    }
}

存在两个问题:

  1. 点击「打开模态框」按钮后,onClose()函数立即被调用
  2. 点击「关闭」按钮后,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 07:37:43