我正在创建这个迷你模块框架,我正在尝试做的是在动态加载的HTML上重用模块定义。这就像使用相同的天气小部件脚本为屏幕上的两个或多个天气小部件供电,一个装载在页面加载,其他装载以后加载。定义模块使用这种格式。
framework.module.create('module_name',function(){
//execute when starting the module
this.init = function(){
//for example, bind a click handler
$('button').on('click',function(){
alert('foo');
});
}
});
模块名称和构造函数存储在数组中,并在页面加载期间执行,如
//store
function create(name,fn){
modules[name] = fn;
}
//execute
function start(){
//for each module definition stored
var module = new modules[name]();
module.init();
}
现在事件处理程序绑定到元素。当模块html已经在页面上时,这是有效的。但是,如果我尝试加载该模块的另一个没有处理程序的HTML副本,则调用start()
会将其与处理程序绑定,但现在将现有/已初始化HTML的处理程序加倍。单击预加载的HTML上的按钮现在会触发两次点击事件。
我无法在模块定义上做到这一点。我需要保留“构造函数/回调函数”格式。另外,我不希望用户为此做变通办法。这必须在框架代码下完成。
如何仅为新添加的完全相同的HTML执行模块脚本?
或
如何阻止脚本影响已初始化的HTML?
答案 0 :(得分:2)
两个难题的答案:jQuery的选择范围或事件委托。
在第一种情况下,您可以确保模块中的选择器仅从传递的context
中获取元素:
framework.module.create('module_name',function(context){
if (!context) {
context = document;
}
//execute when starting the module
this.init = function(){
//for example, bind a click handler
$('button', context).on('click',function(){
alert('foo');
});
}
});
但是,在此示例中,还必须修改start
,以获取其自己的context
参数,并将其传递给模块:
function start(context){
//for each module definition stored
var module = new modules[name](context);
module.init();
}
然后你就这样使用它:start("#myDiv");
。如果您没有传递上下文,它会自动获取document
的选择器上下文。但是,我不确定你是否想要这样做,每次调用时都会传递不同的start
。
或者......你可以使用委托:
framework.module.create('module_name',function(){
//execute when starting the module
this.init = function(){
//for example, bind a click handler
$(document).on('click', 'button', function(){
alert('foo');
});
}
});
这会将事件处理程序附加到document
对象,并在看到其泡泡链通过'button'
时运行它。但是,每次调用module.init
时,这仍会添加事件处理程序。因此,您可以向模块构造函数添加计数器,仅在第一个对象时分配事件处理程序:
framework.module.create('module_name',function(){
var totalModules = 0;
return function(){
totalModules += 1;
//execute when starting the module
this.init = function(){
// if this is the first module being created, and
// no event handlers have yet been attached...
if (totalModules === 1) {
$(document).on('click', 'button', function(){
alert('foo');
});
}
}
}
}());