insertBefore(包含在 addEventListener "click" 中并在元素属性值更改时通过 MutationObserver 调用)被执行多次

insertBefore (enclosed in addEventListener "click" and called via MutationObserver on element attribute value change) is executed multiple times

这是this question的延续。


我为 kat.cr 编写了一个 Greasemonkey userscript,它在 'Torrents awaiting feedback' 弹出窗口中添加了一些额外的按钮。


过程是这样的:(前提是你已经登录并且下载了一些"await feedback"的种子):
单击“反馈”按钮后,会出现 'Torrents awaiting feedback' 弹出窗口,
包含等待反馈的种子,
style.display 属性,例如元素 #fancybox-wrapnone 变为 block (正如我在 Firefox Inspector 中注意到的那样).


我想改进脚本,所以,我正在尝试使用 MutationObserver 为了监视上述元素的属性 style.display 的变化,并在发生变化后添加我的额外按钮。

我的代码是这样的:

document.querySelector('.showFeedback > a').addEventListener('click', function() {


    var observer = new MutationObserver(function(mutations) {
        if (mutations[0].target.style.display == 'block') {
            var parentElement = document.querySelector('div.buttonsline:nth-child(10)');
            var theFirstChild = parentElement.firstChild;
            var button = document.createElement('BUTTON');
            parentElement.insertBefore(button, theFirstChild);
            button.id = 'mybutton1';
            button.innerHTML = 'APPROVE SELECTED';
            document.querySelector('#mybutton1').className = 'siteButton bigButton';
        }
    }).observe(
        document.querySelector('#fancybox-wrap'), {
            attributes: true,
            attributeFilter: ['style']
        }
    );


});

问题是按钮被添加了多次,而不是 1 次。
为什么会这样?我怎样才能解决这个问题?

谢谢

显然,该元素的样式已针对其他属性进行了更改,而不仅仅是 display

检查旧的 display 值是否不是 block(需要 attributeOldValue 参数):

new MutationObserver(function(mutations) {
    if (mutations[0].target.style.display == 'block' && 
        !mutations[0].oldValue.match(/display:\s*block/)) {
        ...............
    }
}).observe(document.querySelector('#fancybox-wrap'), {
    attributeOldValue: true,
    attributeFilter: ['style']
});

或查看按钮 ID:

if (mutations[0].target.style.display == 'block' && 
    !document.querySelector('#mybutton1')) {

或者第一次成功后断开观察者运行:

new MutationObserver(function(mutations, observer) {
    if (mutations[0].target.style.display == 'block') {
        observer.disconnect();
        ...........
    }
})...........

也不需要 var observer = 因为它作为参数传递给回调。