前言:
我知道那里有一個重復的問題。我再次發布它是因為它沒有答案(而且是 4 年前的)。
我想要的一般描述:
我希望能夠Element.style.display = "none"
在將 DOM 加載到視圖之前隱藏 DOM 元素(添加)。
我試過的:
其他帖子指向使用 MutationObserver 并在document
元素上運行它。
為了確保我們能夠在加載 DOM 之前隱藏元素,我們將運行包含 MutationObserver 作為content_script
with的腳本"run_at":"document_start"
。
我做了所有這些,但我仍然看到閃爍(當我加載頁面時元素出現然后很快消失)。
我正在嘗試做的事情:
在我注入的頁面上有一個ul
包含一些文本的內容。我用對填充我的。如果選中該復選框,則包含所述文本是可見的,否則它是隱藏的。我希望它在重繪 之間持續存在,因此使用.li
content_script.js
popup.html
<text, checkbox>
li
storage
一切正常 - 但每當我重繪 頁面時都會閃爍。元素在那里,然后它們就消失了。我不想讓他們一開始就出現!
我的代碼:
當我檢測到我可能洗掉的 DOM 元素已加載時,我會生成一個 Object 來指示我是否應該隱藏或保持該特定 DOM 元素可見。然后我將其設定Element.style.display
為none
或block
相應地。
/**manifest.json
...
"content_scripts": [
{
"matches": [
"some_website_url"
],
"js": [
"content_script.js"
],
"run_at": "document_start"
}
]
...
*/
///content_script.js
const mutationObserver = new MutationObserver((mutations) => {
for (const { addedNodes } of mutations) {
for (const node of addedNodes) {
if (node.tagName) {
if (node.querySelector(potentially_hidden_element_selector)) {
chrome.storage.sync.get("courses", ({ courses }) => {
chrome.storage.sync.set({ "courses": generateCourseList(courses) }, () => {
const courseElements = Array.from(node.closest('ul').querySelectorAll('a[data-parent-key="mycourses"]'))
courseElements.forEach(courseElement => {
const courseName = getCourseName(courseElement)
const isVisible = courses[courseName]
updateCourseElementInSidebar(courseElement, isVisible)
})
})
})
// We found what we were looking for so stop searching
mutationObserver.disconnect()
}
}
}
}
})
mutationObserver.observe(document, { childList: true, subtree: true })
編輯1:
我的方法取決于我可能嘗試隱藏的 DOM 元素 - 所以我認為在 DOM 加載之前generateCourseList
我不能呼叫該方法。chrome.storage.set
當我重繪 頁面時,課程串列最終會填充 DOM。courses
然后,我根據這些課程元素的 innerText 屬性填充存盤物件。我將每個元素的可見性設定為true
或false
基于以下兩個因素之一:如果該課程已在courses
物件中定義,則保持其可見性狀態,如果不是,則將其設定為true
(默認可見)。
如果我沒有對它們的參考,我無法使某些 DOM 元素可見/隱藏。因此,如果我嘗試generateCourseList
在那些特定的 DOM 元素加載之前呼叫,我最終會嘗試檢索所有課程元素 ( document.querySelectorAll('a[data-parent-key="mycourses"]')
) 并且什么也沒有回傳。courses
因為這個,我最終chrome.storage
一無所有chrome.storage.sync.set({ "courses": generateCourseList(courses) }...
。
編輯2:
這是我所有的代碼。我會chrome.storage.sync.get
盡快嘗試,并且盡量不依賴chrome.storage.sync.set
.
我嘗試盡快洗掉這些元素,但這樣做有困難。這是因為我很難知道我想要訪問的內容(課程元素)何時已完全加載。以前,我在檢測一個課程元素何時可見,而當它可見時,我假設所有元素都是可見的。這是一個錯誤。我能夠在它彈出的那一刻訪問一個課程,但有時實際上只加載了 6 個課程元素中的 4 個。我無法對這個數字進行硬編碼,因為它因人而異。我不能一一解決,因為那樣我就不知道什么時候斷開 MutationObserver 了。我使用除錯器并試圖在加載所有 6 個課程元素后很快找到加載的元素,那就是header#page-header.row
元素。我仍然有閃爍,雖然比以前不那么明顯了。
我能做些什么讓它變得不那么引人注目?
function start_mutation_observer() {
chrome.storage.sync.get({ 'savedCourses': {} }, ({ savedCourses }) => {
const observer = new MutationObserver((mutations) => {
for (const { addedNodes } of mutations) {
for (const node of addedNodes) {
// The page header gets updated AFTER the courseList is updated - so once it's in the page, we know the courseElements are too
if (document.querySelector('header#page-header.row')) {
observer.disconnect()
const generatedCourses = generateCourseList(savedCourses)
const courseElements = getCourseElements()
// Set visibility of course elements
courseElements.forEach(courseElement => {
const courseName = getCourseElementTextContent(courseElement);
const isShown = generatedCourses[courseName];
setCourseElementVisibility(courseElement, isShown);
});
chrome.storage.sync.set({ 'savedCourses': generatedCourses });
return
}
}
}
});
observer.observe(document, { childList: true, subtree: true });
// In case the content script has been injected when some of the DOM has already loaded
onMutation([{ addedNodes: [document.documentElement] }]);
});
}
function getCourseElements() {
const COURSE_ELEMENT_SELECTOR = 'ul > li > a[data-parent-key="mycourses"]'
return Array.from(document.querySelectorAll(COURSE_ELEMENT_SELECTOR))
}
function getCourseElementTextContent(courseElement) {
const COURSE_ELEMENT_TEXT_CONTAINER_SELECTOR = 'a[data-parent-key="mycourses"] > div > div > span.media-body'
return courseElement.querySelector(COURSE_ELEMENT_TEXT_CONTAINER_SELECTOR).textContent
}
function generateCourseList(savedCourses) {
// Turns [[a, b], [b,c]] into {a:b, b:c}
return Object.fromEntries(getCourseElements().map(courseElement => {
const courseName = getCourseElementTextContent(courseElement)
const isShown = savedCourses[courseName] ?? true
return [courseName, isShown]
}))
}
function setCourseElementVisibility(courseElement, isShown) {
if (isShown) {
courseElement.style.display = "block"
} else {
courseElement.style.display = "none"
}
}
start_mutation_observer()
編輯 3:
我認為它和現在一樣好。我只重繪 剛剛加載到 DOM 中的課程元素的可見性。現在基本上沒有閃爍(有輕微的閃爍,但沒有我的擴展,它的閃爍量相同)。
這是 MutationObserver 的代碼
function start_mutation_observer() {
let handledCourseElements = new Set()
chrome.storage.sync.get({ 'savedCourses': {} }, ({ savedCourses }) => {
const observer = new MutationObserver((mutations) => {
for (const { addedNodes } of mutations) {
for (const node of addedNodes) {
const courseElements = getCourseElements()
const courseElementsAdded = courseElements.length > handledCourseElements.size
// If a courseElement was added, update visibility of those that weren't already processed
if (courseElementsAdded) {
const generatedCourses = generateCourseList(savedCourses)
courseElements
.filter(courseElement => !handledCourseElements.has(courseElement))
.forEach(courseElement => {
const courseName = getCourseElementTextContent(courseElement)
const courseShouldBeVisible = generatedCourses[courseName];
setCourseElementVisibility(courseElement, courseShouldBeVisible);
handledCourseElements.add(courseElement)
})
}
// The page header gets updated AFTER the courseList is updated - so once it's in the page, we know the courseElements are too
if (document.querySelector('header#page-header.row')) {
observer.disconnect()
chrome.storage.sync.set({ 'savedCourses': generateCourseList(savedCourses) });
return
}
}
}
});
observer.observe(document, { childList: true, subtree: true });
// In case the content script has been injected when some of the DOM has already loaded
onMutation([{ addedNodes: [document.documentElement] }]);
});
}
uj5u.com熱心網友回復:
讀取存盤很慢而且是異步的,所以一開始就需要這樣做:
chrome.storage.sync.get('courses', ({ courses }) => {
chrome.storage.sync.set({ 'courses': generateCourseList(courses) });
const observer = new MutationObserver(onMutation);
observer.observe(document, { childList: true, subtree: true });
onMutation([{addedNodes: [document.documentElement]}]);
function onMutation(mutations) {
for (const { addedNodes } of mutations) {
for (const node of addedNodes) {
if (node.tagName && node.querySelector(potentially_hidden_element_selector)) {
observer.disconnect();
processNode(node, courses);
}
}
}
}
});
function processNode(node, courses) {
const courseElements = Array.from(
node.closest('ul').querySelectorAll('a[data-parent-key="mycourses"]'));
courseElements.forEach(courseElement => {
const courseName = getCourseName(courseElement);
const isVisible = courses[courseName];
updateCourseElementInSidebar(courseElement, isVisible);
});
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/472199.html