我构建了一个模态包装插件(Bootstrap 4(,可以根据需要动态创建对话框。当我使用每个触发按钮的唯一选择器初始化插件时,我可以创建插件的多个实例。
我想初始化它一次,但每个启动按钮都有单独的实例。问题是插件忽略了通过除第一个按钮之外的所有按钮的数据属性设置的选项。无论单击哪个按钮,都会生成完全相同的模式,并且它基于队列中第一个按钮上传递的选项。
这是我当前设置的精简片段。谁能看到我可能错过了什么?
下面是一个示例设置:
初始化
$('.open-modal').myModal();
用于打开模式的两个示例按钮
// Button 1
<button type="button" class="btn open-modal" data-title="Modal 1" data-target="myModal1" data-remote="test.html">Open modal 1</button>
// Button 2 data attributes are ignored. The Modal always renders with options from button 1
<button type="button" class="btn open-modal" data-title="Modal 2" data-position="right" data-target="myModal2" data-remote="test2.html">Open modal 2</button>
插件
...
const defaults = {
type: 'basic',
id: 'myModal' + helper.getRandomInt(9999, 1000),
title: window.document.title,
position: '', //
remote: null, // content to be loaded via Ajax
target: 'myModal', // id of the generated modal
...
};
class Modal {
constructor(el, options) {
this._$el = $(el);
this._el = el;
this._options = options;
this._$el.data(PLUGIN_NAME, this);
this._metadata = this._$el.data();
this._defaults = this.getDefaults();
this._opts = $.extend(true, {}, this._defaults, this._options, this._metadata);
}
// render modal
render(event) {
let cls = this;
let $el = this._$el;
let _bodyID = cls._opts.bodyID;
let _type = cls._opts.type;
let $tpl = $(cls.buildTemplate());
$tpl.appendTo("body").modal({
show: true,
backdrop: cls._opts.backdrop,
keyboard: false
});
// show content
if (_type == 'delete') {
var $mdlBodyID = $(_bodyID);
var $warningContainer = $('<p>');
$warningContainer.text(cls._opts.content).appendTo($mdlBodyID);
} else {
let basicType = _type || 'basic';
cls.log(`${basicType} modal launched`);
$.ajax({
url: cls._opts.remote,
}).done(cls.onSuccess).fail(cls.onError);
}
// remove modal from DOM when closed
$tpl.on(cls._opts.hideEvent, {this: cls}, cls.onHidden);
...
}
...
}
// pluign definition
$.fn[PLUGIN_NAME] = function (options) {
var items = this;
if (items.length) {
var bm = new Modal(items, options);
return items.each(function(e) {
let $item = $(this);
$item.on('click', function(event) {
event.stopPropagation();
event.preventDefault();
bm.render(event.type);
})
});
}
}
编辑 2:快速重新排序代码片段以提高清晰度
结为将$.extend
方法移动到each
循环内的插件定义中。
if (items.length) {
var bm = new Modal(items, options);
return items.each(function(e) {
let $item = $(this);
// override defaults with options or data attributes
let settings = $.extend(true, {}, defaults, options, $item.data());
$item.on('click', function(event) {
event.stopPropagation();
event.preventDefault();
bm.render(event.type, settings);
})
});
}
然后,只需将这些设置传递回 render
方法,该方法现在仅为此目的接受第二个参数。
如果它对任何人都有用,以下是对 render 方法的编辑:
// render modal
render(event, settings) {
let cls = this;
let $el = this._$el;
let _bodyID = cls._opts.bodyID;
let _type = cls._opts.type;
let $tpl = $(cls.buildTemplate(settings));
$tpl.appendTo("body").modal({
show: true,
backdrop: settings.backdrop,
keyboard: false
});
// show content
if (_type == 'delete') {
var $mdlBodyID = $(_bodyID);
var $warningContainer = $('<p>');
$warningContainer.text(settings.content).appendTo($mdlBodyID);
} else {
let basicType = _type || 'basic';
cls.log(`${basicType} modal launched`);
$.ajax({
url: settings.remote,
}).done(cls.onSuccess).fail(cls.onError);
}
// remove modal from DOM when closed
$tpl.on(settings.hideEvent, {this: cls}, cls.onHidden);
...
}