在第三方插件的使用过程中,我们经常需要DOM在加载完成后执行一些操作,如果插件提供了这样的事件接口,那一切都较为简单,但在大部分的情况下,要么是设计者没有考虑到这样的问题,或者没有设计这样的接口,那这时应该怎么办呢?
小组成员经常犯的一个错误是利用if判断,如下:
let dom = document.getElementById('yiifaa')
// dom加载完成后执行操作
if(dom) {
// 执行dom加载完成后的操作,例如echart的初始化操作
echart.init('yiifaa')
}
但是显然,上面的代码只能保证执行的操作不会出错,并不会保证操作一定会执行(dom没加载完成),并且操作永远也得不到执行的机会。
也许你会说,为什么不采用while?如果真那样,那么恭喜你,你的程序死循环了,如下:
let dom = document.getElementById('yiifaa')
// dom没加载完成,一直循环判断
while(!dom) {
continue;
}
// 执行dom加载完成后的操作,例如echart的初始化操作
echart.init('yiifaa')
为什么呢?因为浏览器是单线程执行,而“while(!dom)”一直占着主线程,所以dom永远得不到机会加载到浏览器中。
正确的解决办法是充分利用浏览器的队列特性,如下:
// 声明定时器
var timer = null
// 检查dom是否执行完成
function check() {
let dom = document.getElementById('yiifaa')
if(dom) {
// 执行dom加载完成后的操作,例如echart的初始化操作
echart.init('yiifaa')
// 清除定时器
if(!timer) {
clearTimeout(timer)
}
} else {
// 自我调用
timer = setTimeout(check, 0)
}
}
// 首次执行
check()
结论
在HTML 5中,已经有更好的替代方案-MutationObserver,基于事件触发,效率高,监测的类型不仅多,而且易于使用。