首页 文章

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

提问于
浏览
3

我'm attaching an event handler to my shadow element internally (I' m没有将事件传播给用户),处理 dragover 事件 . 一切正常,直到我试图去除事件 . 似乎当我使用 setTimeout 时,事件被更改,以便它就像被触发一样(事件目标是) <my-element> .

为了使这更清楚; <my-element> 有它的阴影dom,其中包含一些元素 . 如果没有 setTimeout ,则会按预期在其中一个阴影元素上触发事件 . 例如 <my-element> 阴影dom中的 <li><button> . 一旦我尝试使用 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 回答

  • 1

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

    这是一个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);
                }
            };
        })());
    }
    
  • 2

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

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

相关问题