如何用jQuery 1.11模拟Bootstrap的modal相关事件
问题:jQuery 1.11中模拟Bootstrap模态框事件失效
场景描述
使用jQuery 1.11版本,想要模拟Bootstrap模态框的hide.bs.modal、hidden.bs.modal、show.bs.modal、shown.bs.modal事件,但调用$('#addProductModal').modal('hide')时,自定义的$.fn.modal.hide函数从未触发,只有全局的$.fn.hide会执行,且无报错。
原代码如下:
(function($) { var oldshow = $.fn.show; var oldhide = $.fn.hide; $.fn.show = function() { return oldshow.apply(this, arguments); }; $.fn.modal.hide = function() { // <--从未触发 console.log(`hiding modal 1: `, this); oldhide.apply(this, arguments); return this.modal.hidden.apply(this, arguments); }; $.fn.hide.modal = function() { // <--从未触发 console.log(`hiding modal 2: `, this); oldhide.apply(this, arguments); return this.modal.hidden.apply(this, arguments); }; $.fn.hide = function() { // <---此函数触发 console.log(`hiding modal 3: `, this); oldhide.apply(this, arguments); return this.modal.hidden.apply(this, arguments); }; $.fn.modal.hidden = function() { if (this.tagName === `dialog` || this.attr(`role`) === `dialog`) { return this.trigger(`modal.hidden`); } }; })(jQuery); $('#addProductModal').on(`modal.hidden`, function() { // <-- 通过$.fn.hide可正常触发 console.log(`we triggered on hidden`); });
问题根源
Bootstrap的modal()是一个接受命令参数的插件方法,而非直接挂载$.fn.modal.hide这类子方法。你的代码中直接给$.fn.modal添加hide属性,并不会被$(element).modal('hide')调用——因为这种调用方式是传入字符串命令,需要$.fn.modal函数内部去解析处理。
解决方案
重写$.fn.modal函数,让它能识别'show'、'hide'命令,触发对应的前置事件,执行显示/隐藏逻辑,再触发完成事件。同时保留原生show()/hide()的行为,确保非模态框元素不受影响。
修改后的完整代码:
(function($) { // 保存原生方法 var oldShow = $.fn.show; var oldHide = $.fn.hide; // 重写modal插件方法,支持命令参数 $.fn.modal = function(command) { // 遍历匹配的元素(jQuery插件惯例) return this.each(function() { var $modal = $(this); // 仅处理模态框元素(通过role="dialog"或dialog标签判断) if ($modal.is('[role="dialog"], dialog')) { switch(command) { case 'show': // 触发show.bs.modal事件(显示前) $modal.trigger('show.bs.modal'); // 执行原生show方法 oldShow.call($modal); // 触发shown.bs.modal事件(显示完成后) $modal.trigger('shown.bs.modal'); break; case 'hide': // 触发hide.bs.modal事件(隐藏前) $modal.trigger('hide.bs.modal'); // 执行原生hide方法 oldHide.call($modal); // 触发hidden.bs.modal事件(隐藏完成后) $modal.trigger('hidden.bs.modal'); break; // 可扩展其他命令,比如'toggle' case 'toggle': if ($modal.is(':visible')) { $modal.modal('hide'); } else { $modal.modal('show'); } break; } } }); }; // 可选:如果需要通过原生show()/hide()触发模态框事件,可重写这两个方法 $.fn.show = function() { var result = oldShow.apply(this, arguments); // 对模态框元素触发shown事件 this.filter('[role="dialog"], dialog').trigger('shown.bs.modal'); return result; }; $.fn.hide = function() { var result = oldHide.apply(this, arguments); // 对模态框元素触发hidden事件 this.filter('[role="dialog"], dialog').trigger('hidden.bs.modal'); return result; }; })(jQuery); // 事件绑定示例 $('#addProductModal') .on('show.bs.modal', function() { console.log('模态框即将显示'); }) .on('shown.bs.modal', function() { console.log('模态框已显示'); }) .on('hide.bs.modal', function() { console.log('模态框即将隐藏'); }) .on('hidden.bs.modal', function() { console.log('模态框已隐藏'); }); // 调用测试 // $('#addProductModal').modal('show'); // $('#addProductModal').modal('hide');
代码说明
- 重写
$.fn.modal:遵循jQuery插件的遍历惯例,处理'show'/'hide'/'toggle'命令,先触发前置事件(show.bs.modal/hide.bs.modal),再执行原生显示/隐藏逻辑,最后触发完成事件(shown.bs.modal/hidden.bs.modal)。 - 模态框判断:仅对
role="dialog"或<dialog>标签的元素触发事件,避免影响其他元素。 - 原生方法兼容:可选重写
show()/hide(),让直接调用这两个方法时也能触发模态框事件,保持和Bootstrap行为一致。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

