如何将事件绑定到没有DOM对象的函数
How to Bind events to a function without a DOM object
好的,所以我一直在做这个小技巧,以实现在不同时间向一个特定函数添加多个事件所需的功能。
$("#handler").bind("click",function(){ alert(1); });
$("#handler").bind("click",function(){ alert(2); });
$("#handler").bind("click",function(){ alert(3); });
当我简单地调用$("#handler").click()
时,它会触发所有这些事件。
问题是,我可以做到这一点,而不制作一些任意的html对象来绑定它吗?
使用标准javascript函数执行此操作的等效方法是什么?
function handler(){ alert(1); }
function handler(){ alert(2); }
function handler(){ alert(3); }
handler();
^这只是点燃了最后一个,而不是全部三个。如何将多个事件绑定到一个函数而不是DOM元素?
如果您真的只是在寻找一种方法,将单个函数组合到一个更大的"函数集"中,然后可以在以后一次触发,那么这可以通过javascript中的Set
对象来实现。示例:
// define the Set object that you want to store the functions inside:
var handlerFunctionCollection = new Set();
// add individual functions to the Set:
handlerFunctionCollection.add( function(){ console.log(1); } );
handlerFunctionCollection.add( function(){ console.log(2); } );
handlerFunctionCollection.add( function(){ console.log(3); } );
// trigger all functions in set using forEach on Set
// and call() method on stored Function object:
handlerFunctionCollection.forEach(function(handlerFunction) {
if(handlerFunction instanceof Function) {
handlerFunction.call();
}
});
注意,我对你的问题的解释是基于你说的:
当我简单地调用
$("#handler").click()
时,它会触发所有这些事件。
这表明您实际上并不是在寻找将函数直接绑定到事件的方法,而是在一个地方触发多个函数的方法,因为否则您就不会手动触发click
事件。
在Array
对象或类似集合上使用Set
的好处是,Set
的成员是唯一的,因此,如果您多次尝试添加相同的函数(意外或其他),则添加的Function
对象在Set
中只会出现一次,因此,在触发forEach
时,它只会被触发一次,因为它在CCD_ 11中只存在一次,而不是每次添加它。
在JavaScript中,每个函数实际上都是一个函数对象
在Javascript中,如果定义了多个同名函数,那么最后一个函数将实际运行。JavaScript functions
在许多其他语言中与polymorphic
不同,在其他语言中,funcA(parm1)
和funcA(parm1, parm2)
可能是两个独立的函数,其中一个函数的运行取决于传递的参数数量。
在您的情况下,您需要以能够处理函数范围内不同情况的方式声明一个函数。
您正在寻找Observer
或Publisher/Subscriber ("PubSub")
的概念。
这些都是非常容易创建自己
这里有一个稍微清理过的仅限应用程序的代码版本(可能在DOM上运行,或者其他什么),用于运行下面的演示代码。
const trigger = $("#Trigger");
const system = Publisher();
// add my listeners
system
.on("trigger", triggerContentUpdate)
.on("update", updateView)
.on("update", logUpdate); // note how I have two things bound to the same event
// something that kicks off the "trigger" event
// could be a timer, or an AJAX call, or anything else
trigger.onclick = () => system.fire("trigger");
假设你有一个Publisher
库,并且在你的应用程序中有上面的监听器函数,这几乎是你必须编写的所有JS才能使下面的演示工作。
我在实践中编写的库,以及演示的实现如下。
/*** LIBRARY CODE ***/
// Channel.js
const Channel = () => {
const listeners = new Set();
const channel = {
listen(listener) {
listeners.add(listener);
return channel;
},
ignore(listener) {
listeners.delete(listener);
return channel;
},
notify(data) {
listeners.forEach(react => react(data));
return channel;
}
};
return channel;
};
// Publisher.js
const Publisher = () => {
const channels = {};
function getChannel(name) {
const channel = channels[name] || Channel();
channels[name] = channel;
return channel;
}
const publisher = {
on(name, subscriber) {
getChannel(name).listen(subscriber);
return publisher;
},
off(name, subscriber) {
getChannel(name).ignore(subscriber);
return publisher;
},
fire(name, data) {
getChannel(name).notify(data);
return publisher;
}
};
return publisher;
}
/*** END OF LIBRARY CODE ***/
/*** APPLICATION CODE ***/
// const Publisher = require("publisher"); or import Publisher from "publisher";
const $ = selector => document.querySelector(selector);
const trigger = $("#Trigger");
const input = $("#Content");
const output = $("#Result");
const log = $("#Log");
const system = Publisher();
system
.on("trigger", () => {
const content = input.value;
system.fire("update", content);
})
.on("update", content => output.value = content)
// normally, I never use innerHTML, and my logic and view are never attached, but this is dirt-simple now
.on("update", content => log.innerHTML += `<li>[${ (new Date()).toISOString() }]: ${content}</li>`);
trigger.onclick = () => system.fire("trigger");
/*** END OF APPLICATION CODE ***/
<h3>Input</h3>
<div>
<input id="Content" type="text">
<button id="Trigger">Update</button>
</div>
<h3>Output</h3>
<output id="Result"></output>
<h3>Log</h3>
<ul id="Log"></ul>
当然,我使用的是相对现代的语法,但没有什么是不能在旧的兼容代码中重写的,也没有什么是无法转换并赋予polyfill的,可以一直到IE7/8支持。
如果我想让一些任意对象成为一个发布者,我也可以很快做到。
- 将GET请求(HTML字符串)转换为完整的DOM对象
- 在Angular中呈现DOM对象时,如何调用控制器中指定的函数
- 不带dom对象的jquery ajaxComplete()
- 从 DOM 数组中删除 DOM 对象
- Raphael JS:如何从 Dom 对象(Element.node)获取 Raphael 元素
- SVG DOM对象间距/重叠
- DOM对象而不是其他DOM对象
- 如何区分DOM对象和JavaScript对象
- 在提取dom对象后,无法将每个名为tab的元素推送到数组中
- M项目2:是否可以从DOM对象中获取M视图
- Javascript关闭DOM对象事件和事件冒泡
- 如何使用jQuery将重复类添加到DOM对象中
- 当请求DOM对象时,XMLHttpRequest.send()抛出异常
- 从非DOM对象内部调度和处理自定义事件
- dom对象创建javascript和jquery后的事件触发器
- 使用Internet Explorer检索XML DOM对象的URI
- 如何将事件绑定到没有DOM对象的函数
- 使用 Aurelia动态创建一个 dom 对象
- 使用 jQuery 操作 DOM 对象
- 使用多个 css 类将 css 转换属性应用于 DOM 对象时遇到问题