简体   繁体   English

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

[英]How do you debounce/throttle Shadow DOM events?

I'm attaching an event handler to my shadow element internally (I'm not propagating the event out to the user), handling dragover events. 我在内部将一个事件处理程序附加到我的阴影元素(我没有将事件传播给用户),处理dragover事件。 Everything works fine, until I attempt to debounce the events. 一切正常,直到我试图去除事件。 It seems that when I use setTimeout , the event is changed so that it is as if it was fired on (event target is) <my-element> . 似乎当我使用setTimeout ,事件被更改,以便它就像被触发一样(事件目标是) <my-element>

To make this more clear; 为了使这更清楚; <my-element> has it's shadow dom which contains some elements. <my-element>有它的阴影dom,其中包含一些元素。 Without setTimeout the event is fired on one of the shadow elements as expected. 如果没有setTimeout ,则会按预期在其中一个阴影元素上触发事件。 For example an <li> or <button> in the shadow dom of <my-element> . 例如<my-element>的阴影dom中的<li><button> <my-element> As soon as I attempt to debounce the events with setTimeout the event target is changed to <my-element> . 一旦我尝试使用setTimeout去抖动事件,事件目标就会更改为<my-element>

So my question is; 所以我的问题是; can/how do you debounce shadow dom events? 可以/你如何去除影子dom事件?

HTML 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: 使用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);
                }
            };
        })());
    }

[Update] [更新]
Here's a Plunker example . 这是一个Plunker的例子

I put a 1s delay to the setTimeout in the second event handler. 我在第二个事件处理程序中对setTimeout设置了1秒延迟。 So you'll see a bunch of 'DIV' node names scroll by then the 'LIST-EXAMPLE' node names. 所以你会看到一堆'DIV'节点名称然后滚动'LIST-EXAMPLE'节点名称。

The div's are in the shadowRoot. div是在shadowRoot中。

LIST-EXAMPLE is what the user would see on the window scoped events. LIST-EXAMPLE是用户在窗口范围事件中看到的内容。

To get around the event changing, in the third event handler I copy the data off that I want. 为了解决事件的变化,在第三个事件处理程序中,我将数据复制到我想要的位置。

So I guess in my update I answer my own question. 所以我想在我的更新中我回答了我自己的问题。

Here's a Plunker example . 这是一个Plunker的例子

I put a 1s delay to the setTimeout in the second event handler. 我在第二个事件处理程序中对setTimeout设置了1秒延迟。 So you'll see a bunch of 'DIV' node names scroll by then the 'LIST-EXAMPLE' node names. 所以你会看到一堆'DIV'节点名称然后滚动'LIST-EXAMPLE'节点名称。

The div's are in the shadowRoot. div是在shadowRoot中。

LIST-EXAMPLE is what the user would see on the window scoped events. LIST-EXAMPLE是用户在窗口范围事件中看到的内容。

To get around the event changing, in the third event handler I copy the data off that I want. 为了解决事件的变化,在第三个事件处理程序中,我将数据复制到我想要的位置。

So you can do what you would normally do to debounce, but make sure to copy the data that you need off the event, and use the copy in your worker function. 因此,您可以执行通常要进行去抖动的操作,但请确保复制事件所需的数据,并在工作函数中使用该副本。

To update my code from above with a possible solution... 要使用可能的解决方案从上面更新我的代码......

//...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);
            }
        };
    })());
}

You can also pass the data you need as a third parameter of the setTimeout function: 您还可以将所需的数据作为setTimeout函数的第三个参数传递:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM