你如何去抖动/扼杀Shadow DOM事件?

时间:2017-03-11 12:49:25

标签: javascript shadow-dom

我在内部将一个事件处理程序附加到我的shadow元素(我没有将事件传播给用户),处理dragover个事件。一切正常,直到我试图去除事件。似乎当我使用setTimeout时,事件被更改,以便它就像被触发一样(事件目标是)<my-element>

使这一点更清楚; <my-element>有阴影dom,其中包含一些元素。如果没有setTimeout,则会按预期在其中一个阴影元素上触发事件。例如,<li>的影子dom中的<button><my-element>。只要我尝试使用setTimeout去除事件,事件目标就会更改为<my-element>

所以我的问题是;可以/你如何去除阴影dom事件?

HTML

<html>
    <head></head>
    <body>
       <my-element>
           #shadow-root (open)
               <ul>
                   <li draggable="true">
                        <button>Hi</button>
                   </li>
                   <li draggable="true">
                        <button>Hi</button>
                   </li>
               </ul>
              <ul class="drop-target">
              </ul>
       </my-element>
    </body>
</html>

使用Javascript:

    //...class code
    attachEventHandler(){
        let self = this;

        self.shadowElement.addEventListener('dragover', (function debouncedDragOverFactory(){
            let timeoutId = 0,
                evObj;

            return function debouncedDragOver(ev){
                evObj = ev; //Only tracking the last event
                if(!timeoutId){
                    timeoutId = setTimeout(function(){
                        self.onDragOver(evObj); //self is 'this' pointer of the class this code is in.
                                                //onDragOver handles the drag event, obvisouly. 
                        timeoutId = 0;
                    }, 100);
                }
            };
        })());
    }

[更新]
这是一个Plunker example

我在第二个事件处理程序中向setTimeout添加1秒延迟。因此,您将看到一堆'DIV'节点名称滚动到'LIST-EXAMPLE'节点名称。

div位于shadowRoot中。

LIST-EXAMPLE是用户在窗口范围事件中看到的内容。

为了解决事件的变化,在第三个事件处理程序中,我将数据复制到我想要的地方。

2 个答案:

答案 0 :(得分:2)

所以我想在我的更新中我回答了我自己的问题。

这是一个Plunker example

我在第二个事件处理程序中对setTimeout设置了1秒延迟。所以你会看到一堆'DIV'节点名称然后滚动'LIST-EXAMPLE'节点名称。

div位于shadowRoot中。

LIST-EXAMPLE是用户在窗口范围事件中看到的内容。

为了解决事件的变化,在第三个事件处理程序中,我将数据复制到我想要的地方。

所以你可以做你通常做的去抖动,但要确保从事件中复制你需要的数据,并在你的工人函数中使用副本。

使用可能的解决方案从上面更新我的代码......

//...class code
attachEventHandler(){
    let self = this;

    self.shadowElement.addEventListener('dragover', (function debouncedDragOverFactory(){
        let timeoutId = 0,
            evTarget;

        return function debouncedDragOver(ev){
            evTarget = ev.target; //Copy the data off that I need
            if(!timeoutId){
                timeoutId = setTimeout(function(){
                    self.onDragOver(evTarget);
                    timeoutId = 0;
                }, 100);
            }
        };
    })());
}

答案 1 :(得分:1)

您还可以将所需数据作为setTimeout函数的第三个参数传递:

li.addEventListener('dragover', function(e){
    setTimeout(function(nodeName){
        output.textContent = '3' + nodeName + '\n' + output.textContent;    
    }, 2000, e.target.nodeName);
});
相关问题