繁体   English   中英

使用JS触发委托事件

[英]Use JS to trigger a delegated event

我有一个包含许多网格的网页,所有网格都具有相同的 class =“notegrid”。 在每个这样的网格中,都有不同数量的输入,可以是范围、文本或数字。

我在每个音符网格的点击事件中添加了一个名为 extractUserInput(event) 的事件监听器:

let allNoteGrids = document.querySelectorAll("div.notegrid");
    for (let i = 0; i < allNoteGrids.length; i++){
        allNoteGrids[i].addEventListener("click", extractUserInput);
        allNoteGrids[i].addEventListener("blur", extractUserInput);
        allNoteGrids[i].addEventListener("change", extractUserInput);
        allNoteGrids[i].setAttribute("autocomplete", "off");
        // For mobile functionality
        allNoteGrids[i].addEventListener("touchend", extractUserInput);
    }

当用户点击任何输入时,这个 function 确定哪个实际元素引发了点击事件:

function extractUserInput(event){
    
    // Local variables which track which input was used and what type it was
    let slider = event.target.closest("input[type='range']");
    let numeric = event.target.closest("input[type='number']");
    let text = event.target.closest("input[type='text']");

然后 function 执行在被点击的特定元素上发生的任何事情。 现在,所有这一切都完美无缺,但我希望为特定输入触发点击事件。 这是怎么做到的? 我努力了:

document.getElementById("details").click(); 

有问题的网格有 id="details" 但什么也没有发生。 这是因为由于没有单击输入元素,因此没有可从中查找 event.target.closest 的事件。 类似地:

document.getElementById("tasting").click(); 

其中实际输入具有 id="tasting"。

因此,据我所知,没有办法触发委托事件,因为我看不到如何将事件作为参数传递。

因此,根据下面的评论,我尝试了这个:

document.getElementById("tasting").value = 1;
document.getElementById("details").dispatchEvent("click");

第一行更改了 slider 值,第二行应触发 notegrid 元素中 id="details" 的委托事件。 如果这有效,我会在页面上看到由 extractUserInput() 执行的各种更改,但我得到:

未捕获的 TypeError:无法在“EventTarget”上执行“dispatchEvent”:参数 1 不是“Event”类型;

类似地:

document.getElementById("tasting").value = 1;
document.getElementById("tasting").dispatchEvent("click");

然后,从https://developer.mozilla.org/en-US/docs/Web/Events/Creating_and_triggering_events复制我试过这个:

document.getElementById("tasting").value = 1;
    
    function simulateClick() {
            const event = new MouseEvent('click', {
            view: window,
            bubbles: true,
            cancelable: true})
    };
    
    const s = document.getElementById('details');
    s.dispatchEvent(event);

导致此错误:

未捕获的 DOMException:无法在“EventTarget”上执行“dispatchEvent”:事件已被分派。

如果我尝试 id="tasting",也会出现此错误。

由于对其他帖子的评论,我使用了延迟事件监听器,我明白了它们为什么有用——更少的事件监听器应该意味着更快的执行等等,当任何输入被点击或更改时,页面响应完美。 但是,似乎没有办法强制输入事件,除非实际的输入元素专门添加了一个事件侦听器。

虽然我很欣赏所建议的想法,但它们什么也没做。

我是否需要为我希望发生这种情况的情况编写特定的 function,或者有没有办法实现这一点?

一切顺利,

德莫特

您可以尝试触发事件

extractUserInput({target:document.getElementById("tasting")})

这将使用“假”事件 object 作为参数调用您的通用事件处理程序。 它应该会给你预期的结果。

您甚至可以创建一个包装器 function 以使其更容易处理一般情况:

function extractFromId(id){
  extractUserInput({target:document.getElementById(id)})
}

现在您可以通过简单地调用extractFromId("details")extractFromId("tasting")来应用它。

您实际上可以使用.dispatchEvent()方法调度自定义事件 它要求您传递一个事件 object,您可以使用适当的事件构造函数创建该事件。

要模拟点击事件,您可以执行以下操作:

const event = new MouseEvent('click', {
  //Object defining the behavior and properties of the event
  //e.g. bubbles: true/false, cancelable: true/false, etc.
});

document.getElementById("tasting").dispatchEvent(event);

您可以在 MDNjavascript.info上阅读更多相关信息。

所以,我试图根据用户输入或保存的设置来设置页面外观。 20 多个输入中约有 6 个受到影响。

正如我发现的那样,最简单的事情是拥有两个功能:

extractUserInput()
applySettings()

如果用户更改了输入,则 extractUserInput() 对页面进行更改并提取用户的输入值; 如果更改的输入是 6 个特定输入之一,则调用 applySettings() function,但使用用户的输入值。 另一方面,如果已保存设置,则使用元素 id 和设置值调用 applySettings() function。 这 6 个输入的代码只写了一次,在 applySettings() function 中。

这个解决方案非常有效,至少对我来说是这样。

我很遗憾地说,其他任何建议都不适用于委托事件处理程序,因为根据我的经验,function 无法确定更改了哪个输入,除非用户更改了实际的屏幕输入元素。 如果元素在屏幕上发生更改,则 event.target.closest 代码似乎只获取一个元素; 似乎没有办法强迫这一点。

通过委派 function,无需将事件侦听器添加到特定元素。 使用 dispatchEvent 似乎与添加侦听器相同,调用 element.click() 说,然后删除侦听器,所有这些似乎与委托有交叉目的!

在这方面我很可能是错的,但这是我的经验,不管这里建议了什么,我找到的解决方案非常适合我。

所有最好的人,

德莫特

暂无
暂无

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

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