Javascript点击事件监听器只触发一次

Posted

技术标签:

【中文标题】Javascript点击事件监听器只触发一次【英文标题】:Javascript click event listener fires only once 【发布时间】:2020-03-19 16:19:38 【问题描述】:

我有一个 Chrome 扩展程序,可以在推文发布之前拦截和检查推文。为此,我向Tweet 按钮添加了一个事件侦听器。因为内容是动态的,我使用solution proposed in this thread:

initialize : function() 
    let that = this;
    let jsInitChecktimer = setInterval(checkForJsFinished, 111);
    function checkForJsFinished () 
        if (document.querySelector("div[data-testid='tweetButtonInline']"))           
            clearInterval (jsInitChecktimer);
            console.log("Button found");
            that.addSubmitNewTweetClickHandler();
        
    
,

addSubmitNewTweetClickHandler : function() 
    let that = this;
    let buttonSubmitTweet = document.querySelector("div[data-testid='tweetButtonInline']");
    buttonSubmitTweet.addEventListener('click', function(e) 
        console.log("CLICK");
        // Stop default event from happening
        e.preventDefault();
        e.stopImmediatePropagation();
        // Do stuff
    );
,

如果推文顺利通过检查,则会通过使用.trigger('click') 以编程方式触发事件来提交。

这很好用,但只有一次。提交并发布推文后,Tweet 按钮上的事件监听器消失了,我无法拦截下一条推文进行检查。我在再次提交后尝试调用initialize()——也许按钮被删除并新添加到DOM(提交推文时它实际上消失了一会儿)——但querySelector立即找到了按钮。但即使在再次调用initialize() 之后,即使Tweet 按钮也不会触发。

这可能是什么问题?我的问题是我什至不知道在哪里寻找以及如何调试它。

【问题讨论】:

如果您的按钮是传入动态内容的一部分,或者如果您在某个地方重新创建它,您确实需要重新打开监听器。请注意,尽管您应该在实际添加内容或从那里调用适当方法的地方这样做。由于使用定时事件可能运行得太早你也可以使用事件委托 @PatrickEvans 这不是我的按钮。这是 Twitter 网站上用于提交新推文的默认按钮。但是,我假设在提交推文后会重新创建按钮。这就是我第二次尝试调用initialize() 的方式,我再次收到日志消息Button found。我想在我再次调用initialize() 之后,按钮有可能被删除并再次添加。但是我不确定如何正确观察这一点。 您是否可以访问该按钮?尝试为该按钮添加新事件,但在文档包装器上,即使按钮被删除,事件也会保留。 (document).on('click', '.btn-class', function()) 【参考方案1】:

又过了几个小时,我终于弄明白了。问题本质上是新 Twitter 网站的高度动态内容。提交推文后,Tweet 按钮确实被删除并再次添加。需要进行大量更改:

使用MutationObserver 跟踪任何更改。每次发生变化时,调用initialize() 函数。为避免调用过多,我会在某些更改时执行此操作(此处不必要的详细信息)

更改addSubmitNewTweetClickHandler() 方法,以便首先删除事件侦听器以避免重复的侦听器(请注意,与我原来的问题相比,我使用对象,因此使用this

addSubmitNewTweetClickHandler : function() 
  let that = this;
  let buttonSubmitTweet = document.querySelector("div[data-testid='tweetButtonInline']");
  buttonSubmitTweet.removeEventListener('click', this.handleSubmitNewTweetClick ); 
  this.handleSubmitNewTweetClick = this.handleSubmitNewTweetClick.bind(this)
  buttonSubmitTweet.addEventListener('click', this.handleSubmitNewTweetClick );    
,

创建引用函数handleSubmitNewTweetClick需要此更改

总的来说,这仍然不是一个完美的解决方案,因为我给initialize() 打了很多不必要的时间。但是,我无法可靠地识别何时将Tweet 按钮添加到文档中。当我使用MutationObserver 时,添加的节点都没有data-testid 属性,我需要识别正确的按钮。我知道为什么这个属性不存在。也许该属性在添加到按钮后被添加了一段时间,但即使有一个额外的MutationObserver 寻找属性更改,我也可以检测到这一点。

不管怎样,它现在可以工作了,而且只是一个原型。

【讨论】:

以上是关于Javascript点击事件监听器只触发一次的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript监听键盘事件

JavaScript监听键盘事件

javascript中点击鼠标右键触发的事件

javascript --- 实时监听输入框值的变化

uni-app watch事件监听三种用法

uni-app watch事件监听三种用法