JS 异步加载js的三种方案

js文件同步加载的缺点:

页面的js文件一般是同步加载,加载到js文件会阻断html和css的加载,要等到js文件加载完毕,才能继续向下执行,因为js文件可能会操作html和css;但有些js文件不会操作html和css,只是进行初始化数据或者引入工具包,我们希望这些js文件能够并行异步加载,以免一个js文件加载失败,导致后续所有页面都加载不了,影响页面效率。

另外有些工具方法需要按需加载(需要再加载,不用不加载)

js异步加载的三种方案:

1.defer 只有IE9以下能用
异步加载,但要等到dom文档全部解析完(dom树已生成)才会被执行,执行时不会阻塞页面

引入外部js文件

<script type = 'text/javascript' src = 'tools.js' defer = 'defer'> </script>

<script type = 'text/javascript' src = 'tools.js' defer > </script>

也可以将代码写到内部

<script type = 'text/javascript' defer>
	var a = 123; //写在内部
</script>

2.async W3C标准方法
异步加载,加载完就执行,执行时不会阻塞页面,async只能加载外部js,不能把js写在script标签里

<script type = 'text/javascript' src = 'tool.js' async = 'async'></script>

<script type = 'text/javascript' src = 'tool.js' async ></script>

以上两种方法不能很好的处理浏览器兼容问题,因此可以使用第三种方法,更加强大,既可异步加载,也可按需加载

3.创建script节点,插入到DOM中,加载完毕后callBack

var script  = document.createElement('script') //创建
script.type = 'text/javascript' //设置
script.src = 'index.js' //这句执行完 系统就会异步下载指定的文件
...//其他的操作
document.head.appendChild(script) //script标签插入文档后 系统才会解析这个脚本 否则只是下载

但由于系统是异步下载js文件,很可能script标签插入文档的时候,甚至调用js文件中方法的时候,js文件还没有下载完成

var script  = document.createElement('script')
script.type = 'text/javascript'
script.src = 'index.js' //这句执行完 系统就会异步下载指定的文件
document.head.appendChild(script) //script插入文档后 才会解析这个脚本 否则只是下载
test() //系统执行这段语句的时候 js文件可能还未加载完 故会报错

在这里插入图片描述
可以设置定时器,在规定时间后(给js文件下载时间)再执行函数

var script  = document.createElement('script')
script.type = 'text/javascript'
script.src = 'index.js' //这句执行完 系统就会异步下载指定的文件
document.head.appendChild(script) //script插入文档后 才会解析这个脚本 否则只是下载
// test()
setTimeout(function(){ //设置定时器 在规定时间后再执行函数
  test() //这个时候js文件已经下载完成 可以执行
},1000)

在这里插入图片描述
但我们并不清楚要等待多久js文件才会下载完成,那么有没有一个机制能够提醒我们呢?

可使用load事件(并不是只有window才有load事件,但凡需要下载的就有load事件,比如script

var script  = document.createElement('script')
script.type = 'text/javascript'
script.src = 'index.js' //这句执行完 系统就会异步下载指定的文件
script.onload = function(){ //script加载(即js文件下载完)完毕才执行函数
	test()
}
document.head.appendChild(script) //script插入文档后 才会解析这个脚本 否则只是下载

script.onload的能够兼容safari、chrome、firefox、opera,只有IE不兼容,IE没有load事件

但IE有一套自己的方法,IE的script上有一个属性为状态码readyState,默认值是loading,会根据script的加载进度动态地改变属性值,script加载完毕时状态码的值为completeloaded

IE也提供了一套监听机制用于监听script的状态码的变化

script.onreadystatechange = function(){ //监听script的状态码的变化
	if(script.readyState == 'complete' || 'loaded'){ //script加载完毕
		// 逻辑
	}
}

能够解决浏览器兼容问题的js文件加载完成立即执行函数逻辑的工具方法

function loadScript(url,callback){ //callback回调函数可以是函数、字符串、数组等
	var script = document.createElement('script')
	script.type = 'text/javascript'
	if(script.readyState){//IE
		script.onreadystatechange = function(){ //监听script的状态码的变化
		if(script.readyState == 'complete' || 'loaded'){
			callback()
			//eval(callback) 当callback为字符串(情况1)时,eval可将其当作函数来调用
			//obj[callback]() 当callback为字符串(情况2)且所要调用的函数在js文件中是以对象属性的形式存在时
		}
	  }
	}else{ //safari、chrome、firefox、opera
		script.onload = function(){
			callback()
			//eval(callback)
			//obj[callback]()
		}
	}
	script.src = url //js文件的下载最好放在绑定监听事件之后,以免状态码在绑定监听事件之前已完成变化就不会被监听到
	document.head.appendChild(script)
}
// loadScript('index.js',test) 
//会报错 test is not defined 因为在传入test的时候,js文件还在函数中未被加载
loadScript('index.js',function(){ //可传入匿名函数 传入时函数内部逻辑不会被解析
	test()
})loadScript('index.js','test()') //传入字符串形式(情况1)loadScript('index.js','test') //传入字符串形式(情况2)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值