只为构造函数的所有实例触发一次事件侦听器
Firing eventListener only once for all the instances of my constructor?
我在构造函数的所有实例中都有一个共享属性:
function Me() { }
Me.prototype.window = {};
我想在调整大小时更新它的内容window
但我想为每个调整大小事件只做一次,无论我的构造函数创建了多少个实例。
从逻辑上讲,如果我定义 eventListener 如下,在我的实例初始化中,它将被多次触发
function Me() {
window.addEventListener('resize', function() {
this.window = window.outerWidth;
}.bind(this));
}
var a = new Me();
var b = new Me();
// on resize, the callback is called twice
我该怎么做?
我该怎么做?
具有指示是否绑定事件处理程序的标志。然后,在构造函数中,您只需要检查标志:
if (bindHandler) {
// ... bind handler
bindHandler = false;
}
如何/在哪里存储标志取决于您。
以为我会放回我给出的所有答案,以显示 OP 如何没有预先提供所有相关信息。此外,他最终想出并标记为正确的答案是我提供的答案,他击落了。
首先,我提供了可能是最简单的解决方案:
将以下内容完全放在构造函数之外。调整窗口大小时,将更新所有实例的共享属性 - - 。
window.addEventListener('resize', function() {
Me.prototype.window = window.outerWidth;
};
然后,OP 添加了新信息,说明这不好,因为如果不存在Me
实例,回调仍将在原型上注册。
然后我提供了这个,有趣的是,当其他人发布它时,他将其标记为答案。
下一个解决方案必须是在注册事件侦听器之前跟踪是否存在任何Me
实例。这意味着您需要跟踪是否存在任何实例:
// Global variabel to track if Me instances exist
var meInstances = false
var me1 = new Me();
meInstances = true;
if(meInstances){
window.addEventListener('resize', function() {
Me.prototype.window = window.outerWidth;
};
}
但是,当我发布它时,回应是:"你完全让所有的类、构造函数和类似的东西变得无用。没有隔离,你白白添加了很多代码,而且解决方案并不强大。事实上,OP 随后提出了自己的解决方案,该解决方案使用数组来存储实例,然后可以检查数组的长度以查看是否有任何实例。我实际上打算建议这样做,但选择了布尔标志,因为 OP 一直说他想要简单。
所以,我提供了这个:
怎么样:
function Me() {
// This code only runs when instance is being made
// This instance is registers a callback
window.addEventListener('resize', function() {
// Callback modifies single Prototype that all instances share
Me.prototype.window = window.outerWidth;
});
}
Me.prototype.window = {};
现在,我不完全认可这是一个好的解决方案,但从 OP 在每个建议后不断添加的所有约束来看,这似乎是最后的手段。但是,再次被拒绝。
在这里添加我在最终代码中使用的解决方案。
我为完整性添加了一个destroy
方法:
function Me() {
this.init();
}
Me.prototype.window = 0;
// function used to update this.window
Me.prototype.onResizeBound = null;
Me.prototype.onResize = function() {
Me.prototype.window = window.outerWidth;
};
// if there are no instances of Me, initialize the event listener
// then, add this instance to the instances list
Me.prototype.init = function() {
if (this.instances === 0) {
Me.prototype.onResizeBound = this.onResize.bind(this);
window.addEventListener('resize', Me.prototype.onResizeBound);
}
this.instances++;
};
// remove this instance to the instances list
// if there are no more instances in the list, remove the event listener
Me.prototype.destroy = function() {
this.instances--;
if (this.instances === 0) {
window.removeEventListener('resize', Me.prototype.onResizeBound);
}
};
Me.prototype.instances = 0;
例:
var a = new Me(); // added event listener
var b = new Me(); // not added event listener since one is already set
b.destroy(); // not removed event listener since one instance is still there
a.destroy(); // removed event listener since there are not other instances
- jQuery事件侦听器多次启动
- 使用Facebook's EventEmitter是一种让延迟侦听器接收已经发出的事件的方法
- 如何在事件侦听器中每隔一秒执行一次函数
- 一种附加事件侦听器的方法,所有主要的web浏览器都支持
- 只为构造函数的所有实例触发一次事件侦听器
- 事件侦听器会根据一段时间内的点击次数更改变量
- 使用 JavaScript 从 HTML 元素中删除一组特定的事件侦听器
- 重置选择的一次表单的操作侦听器
- 尽管有多个事件侦听器,Javascript 函数只调用一次
- 有没有一种方法可以用事件侦听器检查关闭的窗口AddThis
- 即使在元素被删除后,事件侦听器也会多次触发
- 由于嵌套元素,单击侦听器激发两次
- 事件侦听器从同一指令中多次激发
- 在没有jquery的情况下只执行一次事件侦听器函数
- 添加了事件侦听器,但需要2次单击
- JavaScript事件侦听器运行两次
- 带有参数和innerHTML的事件侦听器只能工作一次
- 是否有一种方法可以在web浏览器中一次删除所有事件侦听器
- 如何在第一次触发后停止滚动事件侦听器
- 使用Google Maps v3中的一个变量(循环、闭包)将事件侦听器附加到一组标记上