原生JS实现DOM加载完成马上执行JS代码的方法


Posted in Javascript onSeptember 07, 2018

用原生JS我们经常使用window.onload事件来加载页面。但是window.onload是在页面元素都加载完毕后才执行,如果页面内有大的图片的话,会在页面展现后好久时间后才执行。所以有时我们需要在DOM载入时马上执行一些函数。jQuery提供了document.ready方法用来代替window.onload。但又不愿意仅为了这一个需求而引入整个JQuery库,于是就把jQuery的方法提取出来,单独使用了。

如果只需要对DOM进行操作,那么这时就没必要等到页面全部加载了。Firefox有DOMContentLoaded事件可以轻松解决,可惜的就是IE没有。

MSDN关于JSCRIPT的一个方法有段不起眼的话,当页面DOM未加载完成时,调用doScroll方法时,会产生异常。那么我们反过来用,如果不异常,那么就是页面DOM加载完毕了。所以 对于Mozilla & Opera 浏览器,在dom树载入后有现成的 DOMContentLoaded 事件。对于Safari 浏览器,有document.onreadystatechange事件,当该触发时,如果 document.readyState=complete时,可视为dom树已经载入。

对于ie,当在iframe内时,同样有document.onreadystatechange事件,对于ie在非iframe内时,只有不断地通过能否执行doScroll判断dom是否加载完毕。

在本例中每间隔5毫秒尝试去执行 document.documentElement.doScroll(‘left')。在ie8下,貌视非iframe窗口也会有 document.onreadystatechange事件,另外也可以在构建自己的框架时使用此函数。

(function(){
  var isReady=false; //判断onDOMReady方法是否已经被执行过
  var readyList= [];//把需要执行的方法先暂存在这个数组里
  var timer;//定时器句柄
 
  ready=function(fn)
  {
   if (isReady )
    fn.call( document);
   else
    readyList.push( function() { return fn.call(this);});
   return this;
  }
 
  var onDOMReady=function(){
   for(var i=0;i< readyList.length;i++)
   {
    readyList[i].apply(document);
   }
   readyList = null;
  }
 
  var bindReady = function(evt)
  {
   if(isReady) return;
   isReady=true;
   onDOMReady.call(window);
   if(document.removeEventListener)
   {
    document.removeEventListener("DOMContentLoaded", bindReady, false);
   }
   else if(document.attachEvent)
   {
    document.detachEvent("onreadystatechange", bindReady);
    if(window == window.top){
     clearInterval(timer);//事件发生后清除定时器
     timer = null;
    }
   }
  };
 
  if(document.addEventListener){
   document.addEventListener("DOMContentLoaded", bindReady, false);
  }
  else if(document.attachEvent)//非最顶级父窗口
 
  {
   document.attachEvent("onreadystatechange", function(){
    if((/loaded|complete/).test(document.readyState))
    bindReady();
   });
 
  if(window == window.top)//在应用有frameset或者iframe的页面时,parent是父窗口,top是最顶级父窗口(有的窗口中套了好几层frameset或者iframe)
  {
   timer = setInterval(function(){
    try
    {
     isReady||document.documentElement.doScroll('left');//在IE下用能否执行doScroll判断 dom是否加载完毕
    }
    catch(e)
    {
     return;
    }
    bindReady();
   },5);
  }
  }
 })();

下面是使用方法:

ready(dosomething);//dosomething为已存在的函数
 //也可以通过闭包来使用
 ready(function(){
  //这里是逻辑代码
 });

以上这篇原生JS实现DOM加载完成马上执行JS代码的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
基于jquery的内容循环滚动小模块(仿新浪微博未登录首页滚动微博显示)
Mar 28 Javascript
基于jQuery的图片左右无缝滚动插件
May 23 Javascript
Javascript中valueOf与toString区别浅析
Mar 19 Javascript
js实现两点之间画线的方法
May 12 Javascript
jQuery Validate 数组 全部验证问题
Jan 12 Javascript
VUE 更好的 ajax 上传处理 axios.js实现代码
May 10 Javascript
使用JS获取SessionStorage的值
Jan 12 Javascript
vue.js实现只弹一次弹框
Jan 29 Javascript
Vue开发实现吸顶效果的示例代码
Aug 21 Javascript
详解使用webpack+electron+reactJs开发windows桌面应用
Feb 01 Javascript
微信公众号网页分享功能开发的示例代码
May 27 Javascript
vue实现购物车的小练习
Dec 21 Vue.js
vue加载完成后的回调函数方法
Sep 07 #Javascript
使用vue-router与v-if实现tab切换遇到的问题及解决方法
Sep 07 #Javascript
VUE DOM加载后执行自定义事件的方法
Sep 07 #Javascript
详解JavaScript事件循环机制
Sep 07 #Javascript
解决vue 引入子组件报错的问题
Sep 06 #Javascript
解决vue v-for 遍历循环时key值报错的问题
Sep 06 #Javascript
vue 解决循环引用组件报错的问题
Sep 06 #Javascript
You might like
PHP获得用户使用的代理服务器ip即真实ip
2006/12/31 PHP
学习discuz php 引入文件的方法DISCUZ_ROOT
2009/06/21 PHP
ThinkPHP采用模块和操作分析
2011/04/18 PHP
php中get_headers函数的作用及用法的详细介绍
2013/04/27 PHP
php function用法如何递归及return和echo区别
2014/03/07 PHP
浅谈htmlentities 、htmlspecialchars、addslashes的使用方法
2016/12/09 PHP
php 使用 __call实现重载功能示例
2019/11/18 PHP
JavaScript入门教程(8) Location地址对象
2009/01/31 Javascript
SOSO地图API使用(一)在地图上画圆实现思路与代码
2013/01/15 Javascript
跟我学习javascript的call(),apply(),bind()与回调
2015/11/16 Javascript
JavaScript和jquery获取父级元素、子级元素、兄弟元素的方法
2016/06/05 Javascript
初识简单却不失优雅的Vue.js
2016/09/12 Javascript
解决ajax不能访问本地文件问题(利用js跨域原理)
2017/01/24 Javascript
Vue.js 2.0 移动端拍照压缩图片上传预览功能
2017/03/06 Javascript
详解angular2实现ng2-router 路由和嵌套路由
2017/03/24 Javascript
深入理解Vue 单向数据流的原理
2017/11/09 Javascript
vue mounted组件的使用
2018/06/18 Javascript
vue-cli webpack 引入swiper的操作方法
2018/09/15 Javascript
纯异步nodejs文件夹(目录)复制功能
2019/09/03 NodeJs
vue路由守卫及路由守卫无限循环问题详析
2019/09/05 Javascript
Vue利用Blob下载原生二进制数组文件
2019/09/25 Javascript
JavaScript实现随机点名器
2020/03/25 Javascript
解决vue无法侦听数组及对象属性的变化问题
2020/07/17 Javascript
jquery实现拖拽添加元素功能
2020/12/01 jQuery
python 远程统计文件代码分享
2015/05/14 Python
PYTHON压平嵌套列表的简单实现
2016/06/08 Python
Python 对象中的数据类型
2017/05/13 Python
python实现批量文件重命名
2019/10/31 Python
python连接mysql数据库并读取数据的实现
2020/09/25 Python
Python爬虫之Selenium实现窗口截图
2020/12/04 Python
CSS3 分类菜单效果
2019/05/27 HTML / CSS
区三好学生主要事迹
2014/01/30 职场文书
长江三峡导游词
2015/01/31 职场文书
人事主管岗位职责
2015/02/04 职场文书
mybatis3中@SelectProvider传递参数方式
2021/08/04 Java/Android
MySql中的json_extract函数处理json字段详情
2022/06/05 MySQL