如何防止Google Polymer更改event.target?

时间:2017-11-09 17:14:01

标签: javascript events dom polymer addeventlistener

我一直在玩Google Polymer Shop demo,并注意到聚合物系统地将DOM事件目标更改为顶级组件(在本例中为<shop-app>)。

  1. 转到https://shop.polymer-project.org/
  2. 打开控制台
  3. 粘贴以下事件侦听器
  4. document.addEventListener('click', function(event){ console.log('DOM click event target:',event.target); });

    1. 点击演示并查看控制台日志
    2. 如您所见,即使您点击不同的元素,聚合物也会系统地将<shop-app>作为event.target返回:

      enter image description here

      此行为的问题在于它会破坏所有使用事件侦听器的外部JavaScript库以检索有关原始事件目标的信息(他们始终看到<shop-app>)。

      作为一种解决方法,我一直在尝试检索原始事件目标(Polymer.dom(event).path[0])并使用它发送新事件(https://pastebin.com/WKhGMrfx)但由于某种原因,我的新事件不会dispatch(我知道我最终会遇到重复的事件,但是我的外部库会起作用,因为至少其中一些事件会有正确的 -  原始 - 事件目标):

      enter image description here

      我的问题:

      Q1:有没有办法防止聚合物被覆盖event.target

      Q2:有没有办法用原始事件目标调度事件?

2 个答案:

答案 0 :(得分:1)

从聚合物商店演示页面的控制台运行此代码,然后检查点击事件的目标

function addEventListenerOverride(obj) {
    if(obj._addEventListener)
        return
    obj._addEventListener = obj.addEventListener;
    obj.addEventListener = function(a,b,c) {
        if(c==undefined)
            c=false;
        this._addEventListener(a,b,c);
        if(!this.eventListenerList)
            this.eventListenerList = {};
        if(!this.eventListenerList[a])
            this.eventListenerList[a] = [];
        //this.removeEventListener(a,b,c); // TODO - handle duplicates..
        this.eventListenerList[a].push({listener:b,useCapture:c});
    };

    obj.getEventListeners = function(a){
        if(!this.eventListenerList)
            this.eventListenerList = {};
        if(a==undefined)
            return this.eventListenerList;
        return this.eventListenerList[a];
    };
    obj.clearEventListeners = function(a){
        if(!this.eventListenerList)
            this.eventListenerList = {};
        if(a==undefined){
            for(var x in (this.getEventListeners())) this.clearEventListeners(x);
                return;
        }
        var el = this.getEventListeners(a);
        if(el==undefined)
            return;
        for(var i = el.length - 1; i >= 0; --i) {
            var ev = el[i];
            this.removeEventListener(a, ev.listener, ev.useCapture);
        }
    };

    obj._removeEventListener = obj.removeEventListener;
    obj.removeEventListener = function(a,b,c) {
        if(c==undefined)
            c=false;
        this._removeEventListener(a,b,c);
        if(!this.eventListenerList)
            this.eventListenerList = {};
        if(!this.eventListenerList[a])
            this.eventListenerList[a] = [];

    // Find the event in the list
    for(var i=0;i<this.eventListenerList[a].length;i++){
    if(this.eventListenerList[a][i].listener==b, this.eventListenerList[a][i].useCapture==c){ // Hmm..
        this.eventListenerList[a].splice(i, 1);
        break;
    }
    }
    if(this.eventListenerList[a].length==0)
        delete this.eventListenerList[a];
    };
}

addEventListenerOverride(Element.prototype);
addEventListenerOverride(document);
addEventListenerOverride(document.body);



document.addEventListener('click', function(event){
    if(event.isCustomized)
        return
    event.stopPropagation();
    event.preventDefault();
    event.stopImmediatePropagation();
    //console.log('DOM click event 1:',event,'target:',event.target);
    var normalizedEvent = Polymer.dom(event);



    //event.oldTarget = event.target;
    //event.target = normalizedEvent.rootTarget;


    // logs #myButton
    //console.info('rootTarget is:', normalizedEvent.rootTarget);
    // logs the instance of event-targeting that hosts #myButton
    //console.info('localTarget is:', normalizedEvent.localTarget);
    // logs [#myButton, document-fragment, event-retargeting,
    //       body, html, document, Window]
    //console.info('path is:', normalizedEvent.path);

    var config = {};
    for(var c in event){
        config[c] = event[c];
    }

    config.bubbles = false;

    var newTarget = normalizedEvent.rootTarget;
    var eventType = event.type;


    console.log("target should be: ", newTarget)

    //config.target = normalizedEvent.rootTarget;

    var fn = function(subEvent){
        subEvent.preventDefault();
        subEvent.stopImmediatePropagation();
        //console.log("subEvent", subEvent.target)
        //subEvent.type = "";
        //console.log("subEvent", subEvent.type)

        var listeners = document.getEventListeners(eventType);
        if(listeners && listeners.length){
            for(var i=0; i<listeners.length;i++){
                var l = listeners[i].listener;
                //l.call();
                l(subEvent)
            }
        }
        newTarget.removeEventListener(eventType, fn)
    }
    var oldEventListeners = (newTarget.getEventListeners(eventType) || []).concat([]);
    console.log("oldEventListeners1", oldEventListeners)
    newTarget.clearEventListeners(eventType);
    newTarget.addEventListener(eventType, fn);
    console.log("oldEventListeners2", oldEventListeners)
    oldEventListeners.forEach(function(a){
        newTarget.addEventListener(eventType, a.listener, a.useCapture);
    })



    var newEvent = new event.constructor(eventType, config);
    newEvent.isCustomized = true;

    //var shopAppEl = document.querySelector("shop-app");

    //shopAppEl.fire(event.type, event.details, {node: newTarget})
    setTimeout(function(){
        try{
            newTarget.dispatchEvent(newEvent);
        }catch(e){
            console.log("error", e)
        }
    },100)


});

document.addEventListener('click', function(event){
    console.log('DOM click event:', event, 'target:', event.target);
});

答案 1 :(得分:1)

在此代码事件中不是真实事件,但它是克隆对象

fstatat