简介

这是我在博客主题和插件开发时遇到的一个问题,因为博文都采用Ajax加载,而代码高亮渲染只会在其js文件第一次加载,或手动调用时才会对文章中的代码进行高亮渲染,怎么让Ajax加载的文章能够及时高亮渲染就是个问题了。想了一下可能的解决方法:

  1. 每次Ajax加载时都重新加载高亮js文件,或执行js语句
  2. 定时执行js语句
  3. 监听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了...不过我是不考虑了。

参考