如何防止隐藏和显示 iframe 的 MutationObserver 闪烁
How to prevent hide and show flickering of MutationObserver for iframe
我正在开发 chrome 隐藏文章的扩展 MV3。
MutationObserver 隐藏文章而不在主框架闪烁。
例如,下面的代码在有新文章时通过向下滚动将 odd 的文章隐藏在 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(in main frame) observe article(in iframe),就会出现闪烁(先显示文章,再隐藏文章)
下面的代码适用于 Korea community site,代码的作用与上面的代码类似。
在 loom
查看它的工作原理
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有关的闪烁?
我用 Whosebug 和 chrome 文档搜索了很多,但找不到解决方案
您可以检测 iframe 在内部导航的时刻,而不是主文档中的 MutationObserver,然后为 iframe 的内容添加 MutationObserver。
checkFrameReady
侦听器将 运行 在 iframe 的 URL 更改之后,但在其导航完成之前。
- 在此期间,DOMException 将在侦听器尝试启动观察器时不断在内部发生。
- 侦听器将通过 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});
}
我正在开发 chrome 隐藏文章的扩展 MV3。
MutationObserver 隐藏文章而不在主框架闪烁。
例如,下面的代码在有新文章时通过向下滚动将 odd 的文章隐藏在 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(in main frame) observe article(in iframe),就会出现闪烁(先显示文章,再隐藏文章)
下面的代码适用于 Korea community site,代码的作用与上面的代码类似。
在 loom
查看它的工作原理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有关的闪烁?
我用 Whosebug 和 chrome 文档搜索了很多,但找不到解决方案
您可以检测 iframe 在内部导航的时刻,而不是主文档中的 MutationObserver,然后为 iframe 的内容添加 MutationObserver。
checkFrameReady
侦听器将 运行 在 iframe 的 URL 更改之后,但在其导航完成之前。- 在此期间,DOMException 将在侦听器尝试启动观察器时不断在内部发生。
- 侦听器将通过 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});
}