【问题标题】:How to listen for changes to the title element?如何监听标题元素的变化?
【发布时间】:2022-02-22 00:47:46
【问题描述】:

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

【问题讨论】:

    标签: javascript dom-events


    【解决方案1】:

    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);
    

    还有Mutation Observer has awesome browser support:

    【讨论】:

    • 看起来很棒,但是当我直接设置document.title时它不起作用: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 }); 有效
    【解决方案2】:

    2022 年更新

    Mutation Observers 无疑是现在要走的路(请参阅Vladimir Starkov's answer),无需回退到下面提到的旧 API。此外,DOMSubtreeModified should be actively avoided 现在。

    我将把这个答案的其余部分留给后代。

    2010 年回答

    您可以在大多数现代浏览器中使用事件来做到这一点(值得注意的例外是所有版本的 Opera 和 Firefox 2.0 及更早版本)。在 IE 中,您可以使用 documentpropertychange 事件,而在最近的 Mozilla 和 WebKit 浏览器中,您可以使用通用的 DOMSubtreeModified 事件。对于其他浏览器,您将不得不退回到轮询 document.title

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

    2015 年更新

    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 的浏览器也支持 DOMSubtreeModified 并且任何其他浏览器支持 onpropertychange .
    • @RobG:是的,我想是的。为了简洁起见,我偶尔会在这方面有点懒惰,使用 Stack Overflow 的答案。在这种情况下,我认为推论还不错:addEventListener 和 DOM 突变事件都是 DOM 级别 2,并且在这两个分支中,缺乏浏览器支持不会引发错误或造成任何伤害。我认为无论如何都无法可靠地检测浏览器是否支持检测标题更改。
    • 或许设置一个监听器,修改标题,看看是否有合适的事件发生,然后恢复标题。
    • 在我的回答中查看现代解决方案
    • @JonKoops: DOMSubtreeModified 是 standardized in the DOM 3 spec 并且在 2015 年我对这个答案的最后一次重大修订时,在不支持 Mutation Observers 的浏览器中用作后备是明智的,但是我绝对同意现在不应该使用它。我会更新的。
    【解决方案3】:

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

    var oldTitle = document.title;
    window.setInterval(function()
    {
        if (document.title !== oldTitle)
        {
            //title has changed - do something
        }
        oldTitle = document.title;
    }, 100); //check every 100ms
    

    【讨论】:

    • 是的,没错。不幸的是,在这种情况下,轮询是唯一的选择。没有事件,监听是不可能的(除非任何 javascript 更改标题也执行回调)。
    • Gecko 浏览器支持监视功能,您可以在其中监视和拦截属性更改。在 IE 中,我认为您可以使用 onpropertychange 或类似方法。
    【解决方案4】:

    这是我的方式,关闭并签入启动

    (function () {
        var lastTitle = undefined;
        function checkTitle() {
            if (lastTitle != document.title) {
                NotifyTitleChanged(document.title); // your implement
                lastTitle = document.title;
            }
            setTimeout(checkTitle, 100);
        };
        checkTitle();
    })();
    

    【讨论】:

      【解决方案5】:

      不要忘记在不再需要时删除监听器。

      原版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])
      

      【讨论】:

        【解决方案6】:
        const observer = new MutationObserver(([{ target }]) =>
          // Log change
          console.log(target.text),
        )
        
        observer.observe(document.querySelector('title'), {
          childList: true,
        })
        

        【讨论】:

          猜你喜欢
          • 2012-11-02
          • 1970-01-01
          • 1970-01-01
          • 2018-04-24
          • 2022-01-05
          • 2022-08-02
          • 2014-02-14
          • 1970-01-01
          • 2021-09-21
          相关资源
          最近更新 更多