如何链式添加 addEventListener?

6

我有以下代码:

document.querySelector('.mySelector').addEventListener("mouseover", function() {
    this.parentNode.parentNode.classList.add("over");
});
document.querySelector('.mySelector').addEventListener("mouseout", function(){
    this.parentNode.parentNode.classList.remove("over");
});

考虑到两个事件都在同一个目标上,是否有一种类似于这样的方法可以链接这两个addEventListener方法?:

document.querySelector('.mySelector').addEventListener("mouseover", function() {
    this.parentNode.parentNode.classList.add("over");
}).addEventListener("mouseout", function(){
    this.parentNode.parentNode.classList.remove("over");
});

执行此操作会产生错误:

未捕获的TypeError错误:无法读取未定义的属性'addEventListener'

4个回答

15

由于addEventListener方法不返回任何内容(实际上它返回undefined),因此无法链接使用该方法。 规范中的说明为:

 interface EventTarget {
  void               addEventListener(in DOMString type, 
                                      in EventListener listener, 
                                      in boolean useCapture);
当然,你可以用你自己的实现来替换 addEventListener
EventTarget.prototype.addEventListener = (() => {
  const addEventListener = EventTarget.prototype.addEventListener;
  return function() {
    addEventListener.apply(this, arguments);
    return this;
  };
})();

document.querySelector('button').addEventListener('hover', () => {
   console.log('hover');
}).addEventListener('click', () => {
   console.log('click');
});

但是,操纵内置原型通常是不建议的,因为它可能会产生意外的副作用。


1
这是我在项目中使用的基本事件链接函数。它不太花哨,但允许链接事件并在需要时使用单个函数处理所有事件类型。
基本的HTML添加了MouseMove类型的事件处理程序,但应该适用于其他事件类型。
要链接事件,您的函数需要在结尾处有一个“return”,以便返回到调用的eventHandler并链接到列表中的下一个函数。
<body>
        <div id="canvas" onmousemove="eventHandler(event)"></div>
</body>

// Call to add event handler to chain
addEventHandler(eventHandler1);

// Call to remove event handler from chain
removeEventHandler(eventHandler1);


var mMoveEventList = new Array();

function addEventHandler(eventHandler) {
    mMoveEventList.push(eventHandler);
}

function removeEventHandler(eventHandler) {
    mMoveEventList.splice(mMoveEventList.indexOf(eventHandler));
}

function eventHandler1(e) {
    console.log("EventHandler1")
    return;  // REQUIRED TO RETURN TO EVENTHANDLER
}

function eventHandler2(e) {
    console.log("EventHandler2")
    return;  // REQUIRED TO RETURN TO EVENTHANDLER 
}

function eventHandler(e) {
    switch (e.type) {
        case "mousemove":
            console.log("mouseMoveEvent");

            if (mMoveEventList.length > 0) {
                for (let i = 0; i < mMoveEventList.length; index++) {
                    mMoveEventList[i]();
                }
            }
            break;
        default:
            # Other event types can be added here
            console.log("Event:", e.type);
            break;
        }
    }
}

0

EventTarget.addEventListener() 不会返回一个对象,因此它不能被链式调用。

因此,您需要使用某种包装器来实现,例如使用JQuery.on()

$('.mySelector')
 .on("mouseover",function() {...})
 .on("mouseout",function() {...})

0
我意识到我对这个问题来得有点晚,但是为了一个个人项目,我需要一个解决方案,所以我进行了一些研究,并发现了如何使链接工作,并且进行了彻底的测试。以下是我的结果:
例如,使用this.can.onmousedown进行链接:
this.can.onmousedown = this.Area2OnMouseDown01.bind(this);
this.can.onmousedown = this.Area2OnMouseDownXX.bind(this);

does not work. In this case, only Area2OnMouseDown01 is called.

使用this.can.addEventListener("mousedown", ...)进行链接,例如:
this.can.addEventListener ("mousedown", this.Area2OnMouseDown01.bind(this), false);
this.can.addEventListenner ("mousedown", this.Area2OnMouseDownXX.bind(this), false);

does work.
    

注意。它们被定义的顺序决定了它们随后被调用的顺序。 例如,使用上述定义:
    -  Area2OnMouseDown01 is called first 
    -  Area2OnMouseDownXX is called second

    If the order defined above is reversed, the order they are then called is
    reversed. For example:
     
    -  Area2OnMouseDownXX is called first
    -  Area2OnMouseDown01 is called second
    

调用的函数不需要指定任何特定的返回值,例如:
    -  return false;
    -  return true;
    
    just simply return:
    
    -  return;
    
    If you omit to specify return at the end of the function, javascript automatically inserts return.
    

被调用的函数不需要以任何其他方式进行修改。例如,这里是我使用的实际函数的简化版本:
    canvasChart.prototype.Area2OnMouseDown01 = function(e) {
        
        this.parm.mouse  = getMouseCoordinates (this.can, e);
        this.parm.mouseX = this.mouseX = this.parm.mouse.x;
        this.parm.mouseY = this.mouseY = this.parm.mouse.y;

        for (var i = 0; i < this.o.yAxis.data.categories.length; i++) {

            if (this.parm.mouseX >= this.o.yAxis.data.categories[i][yid + (i + 1)].x   &&
                this.parm.mouseX <= this.o.yAxis.data.categories[i][yid + (i + 1)].x +
                                    this.o.yAxis.data.categories[i][yid + (i + 1)].w   &&
                this.parm.mouseY >= this.o.yAxis.data.categories[i][yid + (i + 1)].y -
                                    this.o.yAxis.data.categories[i][yid + (i + 1)].h   &&
                this.parm.mouseY <= this.o.yAxis.data.categories[i][yid + (i + 1)].y) {

            //  process request

                return;
                
            }

        }
            
        return;

    }

    canvasChart.prototype.Area2OnMouseDownXX = function(e) {
    
        this.parm.mouse  = getMouseCoordinates (this.can, e);
        this.parm.mouseX = this.mouseX = this.parm.mouse.x;
        this.parm.mouseY = this.mouseY = this.parm.mouse.y;             

        if (this.parm.mouseX >= this.o.yAxis.data.control.x   &&
            this.parm.mouseX <= this.o.yAxis.data.control.x +
                                this.o.yAxis.data.control.w   &&
            this.parm.mouseY >= this.o.yAxis.data.control.y -
                                this.o.yAxis.data.control.h   &&
            this.parm.mouseY <= this.o.yAxis.data.control.y) {

        //  process request
    
            return;
            
        }

        return;
        
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接