【发布时间】:2022-02-22 00:47:46
【问题描述】:
在 Javascript 中,有没有一种技术可以监听标题元素的变化?
【问题讨论】:
标签: javascript dom-events
在 Javascript 中,有没有一种技术可以监听标题元素的变化?
【问题讨论】:
标签: javascript dom-events
5 年后,我们终于有了更好的解决方案。使用MutationObserver!
简而言之:
new MutationObserver(function(mutations) {
console.log(mutations[0].target.nodeValue);
}).observe(
document.querySelector('title'),
{ subtree: true, characterData: true, childList: true }
);
使用 cmets:
// select the target node
var target = document.querySelector('title');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
// We need only first event and only new value of the title
console.log(mutations[0].target.nodeValue);
});
// configuration of the observer:
var config = { subtree: true, characterData: true, childList: true };
// pass in the target node, as well as the observer options
observer.observe(target, config);
【讨论】:
document.title = 'test';
document.__defineSetter__('title', function(val) { document.querySelector('title').childNodes[0].nodeValue = val; });。不幸的是,这可能不适用于所有浏览器。
document.title 时,它也不适合我。 (我使用的是 Chrome 52。)但是,将 childList: true 添加到配置对象修复了它。
new MutationObserver(function() {console.log(document.title);}).observe(document.querySelector('title'),{ childList: true }); 有效
Mutation Observers 无疑是现在要走的路(请参阅Vladimir Starkov's answer),无需回退到下面提到的旧 API。此外,DOMSubtreeModified should be actively avoided 现在。
我将把这个答案的其余部分留给后代。
您可以在大多数现代浏览器中使用事件来做到这一点(值得注意的例外是所有版本的 Opera 和 Firefox 2.0 及更早版本)。在 IE 中,您可以使用 document 的 propertychange 事件,而在最近的 Mozilla 和 WebKit 浏览器中,您可以使用通用的 DOMSubtreeModified 事件。对于其他浏览器,您将不得不退回到轮询 document.title。
请注意,我无法在所有浏览器中对此进行测试,因此您应该在使用前仔细测试。
Mutation Observers 是当今大多数浏览器中使用的方式。有关示例,请参见 Vladimir Starkov 的答案。您可能希望以下某些内容作为旧版浏览器(例如 IE
function titleModified() {
window.alert("Title modifed");
}
window.onload = function() {
var titleEl = document.getElementsByTagName("title")[0];
var docEl = document.documentElement;
if (docEl && docEl.addEventListener) {
docEl.addEventListener("DOMSubtreeModified", function(evt) {
var t = evt.target;
if (t === titleEl || (t.parentNode && t.parentNode === titleEl)) {
titleModified();
}
}, false);
} else {
document.onpropertychange = function() {
if (window.event.propertyName == "title") {
titleModified();
}
};
}
};
【讨论】:
addEventListener 和 DOM 突变事件都是 DOM 级别 2,并且在这两个分支中,缺乏浏览器支持不会引发错误或造成任何伤害。我认为无论如何都无法可靠地检测浏览器是否支持检测标题更改。
没有内置事件。但是,您可以使用setInterval 来完成此操作:
var oldTitle = document.title;
window.setInterval(function()
{
if (document.title !== oldTitle)
{
//title has changed - do something
}
oldTitle = document.title;
}, 100); //check every 100ms
【讨论】:
这是我的方式,关闭并签入启动
(function () {
var lastTitle = undefined;
function checkTitle() {
if (lastTitle != document.title) {
NotifyTitleChanged(document.title); // your implement
lastTitle = document.title;
}
setTimeout(checkTitle, 100);
};
checkTitle();
})();
【讨论】:
不要忘记在不再需要时删除监听器。
原版JS:
const observer = new MutationObserver((mutations) => {
console.log(mutations[0].target.text);
});
observer.observe(document.querySelector("title"), {
subtree: true,
characterData: true,
childList: true,
})
observer.disconnect() // stops looking for changes
或者,如果你使用 React,它可以很好地移除监听器,我写了这个钩子:
React.useEffect(() => {
const observer = new MutationObserver(mutations => {
console.log(mutations[0].target.text)
})
observer.observe(document.querySelector("title"), {
subtree: true,
characterData: true,
childList: true,
})
return () => observer.disconnect()
}, [defaultTitle, notificationTitle])
【讨论】:
const observer = new MutationObserver(([{ target }]) =>
// Log change
console.log(target.text),
)
observer.observe(document.querySelector('title'), {
childList: true,
})
【讨论】: