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>