如何监听标题元素的变化?

IT技术 javascript dom-events
2021-03-05 20:16:00

在 Javascript 中,是否有一种技术可以监听标题元素的变化?

6个回答

5 年后,我们终于有了更好的解决方案。使用MutationObserver

简而言之:

new MutationObserver(function(mutations) {
    console.log(mutations[0].target.nodeValue);
}).observe(
    document.querySelector('title'),
    { subtree: true, characterData: true, childList: true }
);

附评论:

// 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直接设置时,它也不适合我(我使用 Chrome 52。)但是,添加childList: true到配置对象修复了它。
2021-04-30 20:16:00
看起来很棒,但是当我直接设置 document.title 时它不起作用: document.title = 'test';
2021-05-14 20:16:00
作为一种变通方法,您可以添加:document.__defineSetter__('title', function(val) { document.querySelector('title').childNodes[0].nodeValue = val; });不幸的是,这可能不适用于所有浏览器。
2021-05-14 20:16:00
new MutationObserver(function() {console.log(document.title);}).observe(document.querySelector('title'),{ childList: true }); 有用
2021-05-15 20:16:00

您可以在大多数现代浏览器中对事件执行此操作(值得注意的例外是所有版本的 Opera 和 Firefox 2.0 及更早版本)。在 IE 中,您可以使用propertychange事件,document在最近的 Mozilla 和 WebKit 浏览器中,您可以使用通用DOMSubtreeModified事件。对于其他浏览器,您将不得不退回到 polling document.title

请注意,我无法在所有浏览器中对此进行测试,因此您应该在使用前仔细测试。

2015 年 4 月 9 日更新

Mutation Observers 是当今大多数浏览器的首选方式。参见 Vladimir Starkov 的回答示例。您可能希望将以下一些内容作为旧浏览器(例如 IE <= 10 和旧版 Android 浏览器)的后备。

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();
            }
        };
    }
};
在我的回答中查看现代解决方案
2021-04-26 20:16:00
一个好的答案,但使用对象推断,假设所有支持addEventListener 的浏览器也支持DOMSubtreeModified并且任何其他浏览器都支持onpropertychange
2021-05-01 20:16:00
@RobG:是的,我想是的。为简洁起见,我在 Stack Overflow 的回答中偶尔会有点懒惰。在这种情况下,我认为推断还不错:addEventListener并且 DOM 突变事件都是 DOM 级别 2,并且在这两个分支中,缺乏浏览器支持不会引发错误或造成任何伤害。我认为无论如何都无法可靠地检测浏览器是否支持检测标题的更改。
2021-05-03 20:16:00
@VladimirStarkov:是的,Mutation Observers 绝对是现代浏览器的必经之路。不过,我建议对支持进行功能测试,并使用上面的一些作为旧浏览器的后备。
2021-05-05 20:16:00
也许设置一个监听器,修改标题,看看是否有合适的事件发生,然后恢复标题。
2021-05-21 20:16:00

没有内置事件。但是,您可以使用以下方法setInterval来完成此操作:

var oldTitle = document.title;
window.setInterval(function()
{
    if (document.title !== oldTitle)
    {
        //title has changed - do something
    }
    oldTitle = document.title;
}, 100); //check every 100ms
Gecko 浏览器支持监视功能,您可以在其中监视和拦截属性更改。在 IE 中,我认为您可以使用 onpropertychange 或类似方法。
2021-05-08 20:16:00
对,是真的。不幸的是,在这种情况下,轮询是唯一的选择。没有事件,监听是不可能的(除非 javascript 更改标题也会执行回调)。
2021-05-16 20:16:00

这是我的方式,关闭并检查启动

(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])