English 中文(简体)
质询 B. 观察员的回击率
原标题:MutationObserver callback keeps firing
  • 时间:2024-01-18 00:47:44
  •  标签:
  • javascript

我试图让一位穆特人观察员看一页标题的变化,并立即将标题重新定在原案文中。 这部分工作,但首次修改了页标题,我的警钟保持发射,使页数停止。 我在我的呼吁中试图使观察员脱节,这阻止了观察员的 lo,但我实际上需要保持观察,因此这是一个解决办法。

我做了什么错误?

function resetTitle(title) {
    document.title = title[0].oldValue;
    console.info("Reset the page title.");
}

let observer = new MutationObserver(resetTitle);

observer.observe(document.querySelector( title ), {
  childList: true,
  subtree: true,
  characterDataOldValue: true
});
最佳回答

这正是你想做的(根据凯希多的更正,更新如下)。

var originalTitle = document.title;
    
    function resetTitle(title) {
        if( originalTitle != document.title ){    
        // disable the observer while you make the change
                observer.disconnect();
                document.title = originalTitle;
                console.info("Reset the page title.");
        
                // now enable it again
                observer.observe(document.querySelector( title ), {
                childList: true,
                subtree: true,
                characterDataOldValue: true
                });
            }
        
    }
    
    let observer = new MutationObserver(resetTitle);
    
    observer.observe(document.querySelector( title ), {
      childList: true,
      subtree: true,
      characterDataOldValue: true
    });
问题回答

First, when the document.title is set, the string replace all algorithm is used, which will replace all the previous content of the <title> element with a new TextNode.
Doing so, there is no CharacterData mutation occurring, only a childList one, which will not fill the previousValue field.

document.title = "original title";
// StackSnippets don t set a title, so we need to wait after we set the initial
// title before starting our observer
setTimeout(() => {
  function resetTitle(title) {
      console.log("oldValue:", title[0].oldValue);
      console.log("type:", title[0].type);
  }

  let observer = new MutationObserver(resetTitle);

  observer.observe(document.querySelector( title ), {
    childList: true,
    subtree: true,
    characterDataOldValue: true
  });
  document.title = Math.random();
}, 100)

如果标题是直接修改现有的<代码>TextNode,你本可使用:

document.title = "original title";
// StackSnippets don t set a title, so we need to wait after we set the initial
// title before starting our observer
setTimeout(() => {
  function resetTitle([record]) {
    console.log("oldValue:", record.oldValue);
  }

  let observer = new MutationObserver(resetTitle);
  observer.observe(document.querySelector( title ), {
    subtree: true,
    characterDataOldValue: true,
  });

  document.querySelector( title ).firstChild.data = Math.random();
}, 100);

So what you need is actually to handle both the possible CharacterData mutation, and the childList one, by looking at the removedNodes[0].data to get the old value.
But if you re going to modify the title again in your handler, you will trigger once more the observer s callback, with this time, the new title being set as the old one. So instead, the best is to store the original value that you want to keep from outside of the observer s callback, and to check in the callback if the title needs an update or not:

document.title = "original title";

setTimeout(() => {
  // Store the original title when you start the observer
  const originalTitle = document.title;
  function resetTitle([record]) {
    // Only if needed, even setting to the same value would trigger a childList change.
    if (document.title !== originalTitle) {
      document.title = originalTitle;
      console.log("resetting title");
    }
  }
  let observer = new MutationObserver(resetTitle);
  observer.observe(document.querySelector( title ), {
    childList: true,
    subtree: true,
    characterDataOldValue: true,
  });
  document.querySelector( button.title ).onclick = e =>
    document.title = Math.random();
  document.querySelector( button.data ).onclick = e =>
    document.querySelector( title ).firstChild.data = Math.random();
}, 100);
<button class=title>change through `document.title`</button>
<button class=data>change through `TextNode.data`</button>

你创建了反馈循环。 避免反馈循环的一个简单办法是简单地将这一变化与现值相比较,而不必对订阅进行微观管理。

您或许也希望获得您的原始头衔。


const originalTitle = document.title;

function resetTitle(title) {
    // Avoid loop by ignoring self change.
    if (originalTitle === title[0].newValue) {
      return    
    }
    document.title = originalTitle;
    console.info("Reset the page title.");
}

另一种做法是,仅仅无视事件内容,对照日程核对标题。 这也将避免反馈。


const originalTitle = document.title;

function resetTitle(_title) {
    // Avoid loop by ignoring self change.
    if (document.title !== originalTitle) {
      document.title = originalTitle;
      console.info("Reset the page title.");
    }
}

你们需要打断观察员,在方案上和在方案上公布所有权价值;控制,只有这样,你才能用观察员的选择来调整同一职能。

const elTitle = document.querySelector( title );

const resetTitle = (mutList) => {
  mutList.forEach(mut => {
    if (mut.type === "childList") {
      observer.disconnect(); // Detach first (to prevent infinite loop)
      elTitle.textContent = mut.removedNodes[0].nodeValue; // Reset to old
      observer.observe(elTitle, observerOptions); // Reattach
    }
  });
};

const observer = new MutationObserver(resetTitle);
const observerOptions = { childList: true };

observer.observe(elTitle, observerOptions); // Init attach

// THIS DEMO ONLY
setInterval(() => { elTitle.textContent = "test"; }, 2000);




相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签