无论添加事件的顺序如何,您如何强制首先运行javascript事件?

我有javascript,人们在他们的页面中包括。 在我的javascript中,我有一个jQuery版本(1.8为了方便参考),它被划分为自己的命名空间,并通过全局变量引用(但不是“$”或“jQuery”的两个默认变量之一) 。 这允许用户在他们的页面中使用jQuery,并且不会干扰我在函数内部执行的操作。

所以我们有一个页面已经有jQuery(1.4),并且一切正常,除了用户和我的代码都在元素上听“click”事件,而他们的第一个,所以在他们做的那几个事件上返回false,jQuery停止传播,我的事件永远不会被触发。 我需要先举办活动。 用户希望我的onClickfunction仍然有效。

现在我知道jQuery通过_data()对象在内部保持自己的事件顺序,通过它可以取消绑定现有事件,绑定我的事件,然后重新绑定现有事件,但这只适用于通过该实例绑定的对象的jQuery。 我宁愿不盲目地寻找jQuery对象,希望冲突是由用户自己的jQuery版本引入的。 毕竟当用户不通过jQuery绑定事件时会发生什么? 试图操纵页面中现有的jQuery对象并不是一个好的解决方案。

我知道,根据浏览器,他们使用addEventListener / removeEventListener或attachEvent / detachEvent。 如果我只能获得已添加事件的列表,我可以按照我想要的顺序重新绑定它们,但我无法找到方法。 通过chrome检查来查看DOM我没有看到onclick绑定到任何地方(不在对象上,也不在窗口或文档上)。

我正试着弄清楚jQuery绑定其监听的确切位置。 为了能够控制自己事件的顺序,jQuery必须全面地听某个地方,然后开启自己的function吗? 如果我能弄清楚那里做了什么,我可能会深入了解如何确保我的活动始终是第一位的。 或者也许有一些我在谷歌上找不到的JavaScript API。

有什么建议?

我们通过添加一个在事件链的头部插入事件的jQuery扩展来解决这个问题:

 $.fn.bindFirst = function(name, fn) { var elem, handlers, i, _len; this.bind(name, fn); for (i = 0, _len = this.length; i < _len; i++) { elem = this[i]; handlers = jQuery._data(elem).events[name.split('.')[0]]; handlers.unshift(handlers.pop()); } }; 

然后,绑定您的事件:

 $(".foo").bindFirst("click", function() { /* Your handler */ }); 

十分简单!

正如Bergi和Chris Heald在评论中所说,事实certificate,没有办法从DOM中获取现有事件,也没有方法可以“先”插入事件。 它们按照设计插入的顺序被触发,并被设计隐藏。 正如一些海报所提到的,您可以访问通过jQuery的数据使用的jQuery实例添加的那些,但就是这样。

还有另一种情况,您可以在代码运行之前绑定的事件之前运行,如果他们使用“onclick”HTML属性。 在这种情况下,您可以编写一个包装函数,因为在下面的一个相当过分的评论中没有必要指出。 虽然这对我提出的原始问题的实例没有帮助,现在很少有事件以这种方式绑定(大多数人和框架现在使用addEvent或attachEventListener),这是一个你可以解决的场景“先跑”的问题,既然很多人现在都在寻找答案,我想我会确保答案是完整的。

我遇到了一个相反的情况,我被要求包括一个库,它在元素上使用event.stopImmediatePropagation()到我们的网站。 所以我的一些事件处理程序被跳过了。 这是我做的( 这里回答):

 Button 

警告 :这不是绑定事件的推荐方法,其他开发人员可能会因此而谋杀您。

就这样说,我认为如果你覆盖这些函数的本机实现,这可能是可能的。 这是一种糟糕的做法 – 在开发库来改变本机实现时非常糟糕,因为它很容易与其他库冲突。

但是,为了完整性,这里有一种可能性(完全未经测试,只是展示了一般概念):

 // override createElement() var temp = document.createElement; document.createElement = function() { // create element var el = document.createElement.original.apply(document, arguments); // override addEventListener() el.addEventListenerOriginal = el.addEventListener; el._my_stored_events = []; // add custom functions el.addEventListener = addEventListenerCustom; el.addEventListenerFirst = addEventListenerFirst; // ... }; document.createElement.original = temp; // define main event listeners function myMainEventListeners(type) { if (myMainEventListeners.all[type] === undefined) { myMainEventListeners.all[type] = function() { for (var i = 0; i < this._my_stored_events.length; i++) { var event = this._my_stored_events[i]; if (event.type == type) { event.listener.apply(this, arguments); } } } } return myMainEventListeners.all[type]; } myMainEventListeners.all = {}; // define functions to mess with the event list function addEventListenerCustom(type, listener, useCapture, wantsUntrusted) { // register handler in personal storage list this._my_stored_events.push({ 'type' : type, 'listener' : listener }); // register custom event handler if (this.type === undefined) { this.type = myMainEventListeners(type); } } function addEventListenerFirst(type, listener) { // register handler in personal storage list this._my_stored_events.push({ 'type' : type, 'listener' : listener }); // register custom event handler if (this.type === undefined) { this.type = myMainEventListeners(type); } } // ... 

在这方面需要做更多的工作才能真正锁定它,再次,最好不要修改本机库。 但这是一项有用的心理练习,有助于展示JavaScript在解决此类问题时提供的灵活性。