0

我正在开发隐藏文章的 chrome 扩展 MV3。

MutationObserver 隐藏文章而不在主框架闪烁。

例如,当有新文章时,下面的代码通过向下滚动隐藏了奇数在Reddit上的文章。

function eraseDealer(){
    console.log("erase Function Call");
    let ls = document.querySelectorAll('#SHORTCUT_FOCUSABLE_DIV > div:nth-child(4) > div > div > div > div._3ozFtOe6WpJEMUtxDOIvtU > div._31N0dvxfpsO6Ur5AKx4O5d > div._1OVBBWLtHoSPfGCRaPzpTf._2OVNlZuUd8L9v0yVECZ2iA > div.rpBJOHq2PR60pnwJlUyP0 > div');
    let idx;

    for(idx=ls.length-1; idx>=0; idx--){
        if(idx%2===0) continue
        ls[idx].setAttribute('style', 'display: none;');
    }
}

eraseDealer();

var config = { childList: true, characterData: false };
var htmlBody = document.getElementsByClassName('rpBJOHq2PR60pnwJlUyP0')[0];

var observerErase = new MutationObserver(function(mutations, observer) {
    mutations.forEach(function(mutation) {
        console.log("Mutation call - erase");
        eraseDealer();

    });
});

observerErase.observe(htmlBody, config);

但是如果MutationObserver(在主框架中)观察文章(在iframe中),就会出现闪烁(先显示文章,然后隐藏文章)

下面的代码在韩国社区网站上工作,代码的作用与上面的代码相似。

看看它在织机上是如何工作的

function eraseDealer(){
    let inner_iframe = document.getElementById('cafe_main').contentWindow;
    let post_table = inner_iframe.document.querySelectorAll('#main-area > div.article-board.m-tcol-c')[1];
    if(post_table !== undefined){
        let ls = post_table.querySelectorAll('div.article-board.m-tcol-c > table > tbody > tr');

        let idx;
        let dealer_link = 'https://cafe.pstatic.net/levelicon/1/1_150.gif';

        for(idx=ls.length-1; idx>=0; idx--){
            let src = ls[idx].querySelector('td.td_name > div > table > tbody > tr > td > span > img').getAttribute('src');
            let nickName = ls[idx].querySelector('td.td_name > div > table > tbody > tr > td > a').textContent;
            if(src === dealer_link){
                ls[idx].setAttribute('style', 'display: none;');
            }
        }
    }
}

eraseDealer();

var config = { attributes: true, childList: true, subtree: true, characterData: false };
var target = document.querySelector('#main-area');

var observerErase = new MutationObserver(function(mutations, observer) {
    mutations.forEach(function(mutation) {
        console.log("Mutation call - erase");
        eraseDealer();
    });
});

observerErase.observe(target, config);

为什么我不在 iframe 中而是在主框架中插入 mutationObserver 是当 iframe url 更改时,mutationObserver 被删除

请参阅我之前关注的问题

是否有任何 MutationObserver 属性需要停止与 iframe 相关的闪烁?

我用 stackoverflow 和 chrome 文档搜索了很多,但我找不到解决方案

4

1 回答 1

0

您可以检测 iframe 在内部导航的时刻,而不是主文档中的 MutationObserver,然后为 iframe 的内容添加 MutationObserver。

  1. 侦听器将checkFrameReady在 iframe 的 URL 更改之后,但在其导航完成之前运行。
  2. 在这段时间内,当 DOMException 尝试启动观察者时,它会在监听器内部不断发生。
  3. 侦听器将通过 requestAnimationFrame 重复自身,直到 iframe 最终完成对新 URL 的导航。那时 iframe 与主页面同源,我们的代码将能够访问 iframe 的内容并启动观察者。
var SEL = '.td_name img[src="https://cafe.pstatic.net/levelicon/1/1_150.gif"]';
var fw = document.querySelector('#cafe_main').contentWindow;
fw.addEventListener('unload', checkFrameReady);

function checkFrameReady(e) {
  if (!e.type) {
    try {
      startObserver(new fw.MutationObserver(eraseDealer));
      fw.addEventListener('unload', checkFrameReady);
      return;
    } catch (e) {}
  }
  requestAnimationFrame(checkFrameReady);
}
function eraseDealer(mutations, observer) {
  let stopped;
  for (const { addedNodes } of mutations) {
    for (const n of addedNodes) {
      if (!n.tagName) continue;
      const elems = n.matches(SEL) && [n] ||
        n.firstElementChild && n.querySelectorAll(SEL);
      if (!elems || !elems.length) continue;
      if (!stopped) { stopped = true; observer.disconnect(); }
      elems.forEach(el => el.closest('.td_name').closest('tr').remove());
    }
  }
  if (stopped) startObserver(observer);
}
function startObserver(observer) {
  observer.observe(fw.document.body || fw.document.documentElement,
    {childList: true, subtree: true});
}
于 2021-08-23T10:54:10.073 回答