【问题标题】:Click a button on dynamically changed element单击动态更改元素上的按钮
【发布时间】:2016-02-23 19:04:33
【问题描述】:

当您在 Facebook 聊天中链接到某个网站时,我总是单击小 x,这样预览就会消失。我讨厌这样做,因为我每天可能发送数百个链接,而预览只是垃圾 9/10 次。

我正在创建一个用户脚本来解决这个问题,但由于它是动态加载的,我不能在按钮出现时简单地单击它。这是我想点击按钮时的样子:

$(".fbNubFlyoutAttachments").find("button:contains('Remove')").click();

基本上它会找到 fbNubFlyoutAttachments 类,然后找到包含“Remove”的按钮。然后它单击元素,预览消失。很简单。

但是,当我要检查链接何时发布时......我们在这里遇到了一些棘手的问题。这是我迄今为止尝试过的:

$(document).bind("DOMSubtreeModified ", ".fbNubFlyoutAttachments", function(){
    $(".fbNubFlyoutAttachments").find("button:contains('Remove')").click();
});

但是。 $(document).bind("DOMSubtreeModified" 触发了很多,因为 DOM 变化很大,这导致堆栈几乎立即被填充,然后页面冻结。最好只做$(".fbNubFlyoutAttachments").bind("DOMSubtreeModified",但这是不可能的(据我所知)。

这是我目前所做的,它有效,但可能需要一秒钟才能触发,并且它正在使用计算资源而不需要它:

setInterval(function() {
    $(".fbNubFlyoutAttachments").find("button:contains('Remove')").click();
}, 1000);

我怎样才能通过我的用户脚本很好地做到这一点?任何帮助表示赞赏!谢谢。

【问题讨论】:

    标签: javascript greasemonkey userscripts tampermonkey


    【解决方案1】:

    您可以使用MutationObserver,而不是使用DomSubtreeModified 事件which is deprecated

    DOM mutation events 在性能和稳定性方面存在问题,所以这可能是当您将DomSubtreeModified 事件绑定到文档时所有冻结的原因,更多信息here

    所以你可以尝试在tampermonkey中使用MutationObserver,如下:

    // ==UserScript==
    // @name         New Userscript
    // @namespace    http://tampermonkey.net/
    // @version      0.1
    // @description  try to take over the world!
    // @author       You
    // @match        https://www.facebook.com/*
    // @grant        none
    // @require      http://code.jquery.com/jquery-latest.js
    
    // ==/UserScript==
    /* jshint -W097 */
    'use strict';
    
    
    $(function() {
        // element to observer
        var body = document.querySelector('body');
    
        // create the trigger function
        var observer = new MutationObserver(function(mutations, observer) {
            $(".fbNubFlyoutAttachments").find("button:contains('Remove')").click();
        });
    
        // configure the element to observe and the changes you want to check
        observer.observe(body, { subtree: true, childList : true, characterData : true});
    
    
    });
    

    还要检查attributes of the observer method.

    此外,您可以根据在MutationObserver callback 中接收到的对象的突变数组来过滤操作。

    希望对你有帮助,

    【讨论】:

    • 感谢您的回答!运行脚本时出现failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'. 错误。可能是因为发生某些事情时元素会动态更改吗?因为它是 Facebook,我基本上可以打开 10 个聊天,所以我需要在任何给定时间选择所有打开的窗口(这就是为什么我现在有一个 setInterval(function()..))。
    • @snorlax 抱歉,我没有很好地解释自己,我也没有尝试我提供的第一个解决方案......我进行了评论,所以我希望现在它更准确 :)
    • 哇,它看起来真的很棒!然而,它做了很多不必要的计算。每次你在聊天中输入一个角色,它都会触发点击,即使没有发送链接。此外,当您加载页面时,它会触发 15-20 次。这不是不必要的吗?不过效果很好!
    • @Snorlax 是的太多了。您可以删除characterData : true 选项,以避免您在聊天中输入的每个角色触发事件。此外,您可以使用其他选项或返回突变,以减少不必要的计算,对不起,我不是MutationObserver:) 的专家。
    • 是的,我肯定会玩一下它!非常感谢!这比使用间隔要好得多哈哈。我没有在 body-tag 上做选择器,而是继续往下看 #pagelet_dock - 使用 body-selector,它基本上会在页面上发生任何事情时触发。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-11
    • 2018-05-21
    • 1970-01-01
    相关资源
    最近更新 更多