使用MutationObserver和DOMSubtreeModified监听HTML中title的变化
简介
这是我在博客主题和插件开发时遇到的一个问题,因为博文都采用Ajax加载,而代码高亮渲染只会在其js文件第一次加载,或手动调用时才会对文章中的代码进行高亮渲染,怎么让Ajax加载的文章能够及时高亮渲染就是个问题了。想了一下可能的解决方法:
- 每次Ajax加载时都重新加载高亮js文件,或执行js语句
- 定时执行js语句
- 监听DOM,DOM出现变化时则执行js语句
方法1是最简单明了的,但因为代码高亮属于插件功能,不太能够知道Ajax会加载哪些内容,不太容易挂“钩子”上去。方法2效率太低不考虑。就只有方法3啦,因为我只需要在加载新文章时高亮渲染,所以DOM只用监听title就好了。
监听DOM一般用DOMSubtreeModified或MutationObserver,但发现DOMSubtreeModified已经deprecated,而MutationObserver只在比较新的浏览器上才支持,所以考虑同时使用这两个方法,来支持绝大多数浏览器。
MutationObserver
W3C MutationObserver介绍:[4.3 Mutation observers]
MutationObserver IE要11及以上,详细可以看[Can I use Mutation ?]
直接贴代码吧,也没多少晦涩难懂的
var titleEl = document.getElementsByTagName("title")[0];
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var MutationObserverConfig={
childList: true,
subtree: true,
characterData: true
};
var observer=new MutationObserver(function(mutations){
do_render();
});
observer.observe(titleEl,MutationObserverConfig);
都是一个套路,就是想要监听DOM的不同内容可能需要修改MutationObserverConfig
。这样每当title内容有变化时,就会触发do_render()
。
DOMSubtreeModified
DOMSubtreeModified实际上是属于MutationEvent的,W3C MutationEvent介绍:[C.4 Legacy MutationEvent events]
注意MutationEvent已经deprecated了,如果不是为了兼容老的浏览器,请使用MutationObserver
DOMSubtreeModified的使用简单多了,直接上代码
var titleEl = document.getElementsByTagName("title")[0];
titleEl.addEventListener("DOMSubtreeModified", function(evt) {
do_render();
}, false);
这样每当title内容有变化时,就会触发do_render()
。
结合MutationObserver和DOMSubtreeModified
当然是优先使用MutationObserver了,如果MutationObserver不支持,就使用DOMSubtreeModified,如果DOMSubtreeModified也不支持的话...就不支持了...
function do_render(){
Prism.highlightAll();
}
var render_prism=function(){
do_render();
var titleEl = document.getElementsByTagName("title")[0];
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
if(MutationObserver){
var MutationObserverConfig={
childList: true,
subtree: true,
characterData: true
};
var observer=new MutationObserver(function(mutations){
do_render();
});
observer.observe(titleEl,MutationObserverConfig);
}
else if(titleEl.addEventListener){
titleEl.addEventListener("DOMSubtreeModified", function(evt) {
do_render();
}, false);
}
else{
console.log('unsupported browser');
}
};
使用MutationObserver和DOMSubtreeModified基本可以兼容IE9以来的所有浏览器了,但如果你还想兼容IE8的话...可以考虑我之前说的方法2了...不过我是不考虑了。
参考
- 4.3 Mutation observers - W3C DOM4
- Can I use Mutation - Can I use... Support tables for HTML5, CSS3, etc
- C.4 Legacy MutationEvent events - UI Events Specification
- javascript - how to listen for changes to the title element? - Stack Overflow
- javascript - Fire jQuery event on div change - Stack Overflow
- javascript - Is there a jQuery DOM change listener? - Stack Overflow
- 用 MutationObserver 和 Mutation events 监听 DOM 变化 | Hans Chan Blog