[TOC]
前言
js脚本的下载和执行会阻塞页面和其他文件的下载,如果不做任何处理那么每一个文件都必须等到前一个文件加载完成并且执行后才开始下载。需要下载的文件一多,页面加载时就会处于卡顿状态,显示一片空白,交互体验非常不好。
解决
1.js加载放置于HTML文档底部
由于js脚本会阻塞后面文件的加载,因此可以将js脚本的加载放置在整个HTML文档底部,让其最后加载,从而减少对其他文件和页面渲染的阻塞。
<html>
<head>
<title>这是一个网页</title>
<link rel="stylesheet" type="text/css" href="">
</head>
<body>
<p>Hello Javascript</p>
<script type='text/javascript' src=''></script>
</body>
</html>
2.合并脚本
尽量减少HTML页面中<script>
标签数量(不管是外链接js还是内链接js),浏览器每次遇到一个<script>
标签都会加载并执行,我们可以采用合并文件的方式减少<script>
的数量,这样只需要一个<script>
标签就可以完成页面的交互.
3.延迟脚本
<script>
标签上的defer和async属性可以延迟脚本的执行,并且可以与其他文件并行加载,不会造成阻塞。
<script type='text/javascript' defer></script>
<script type='text/javascript' async></script>
二者区别在于:async属性会在脚本加载完成后自动执行,而defer会等到页面加载完成后执行。
值得注意的是 defer 的执行会在load
之前。
4.使用window.onload
事件
window.onload
事件会等到页面所有东西都准备完成时执行,可以采用这一机制,在onload
事件后加载js脚本,避免js脚本对其他文件的和页面渲染的阻塞。
5.动态创建<script>
标签
采用动态创建的方式添加<script>
标签,由于内联代码块是最后执行的,所以插入的<script>
标签会在最后加载执行,从而减少了性能的消耗。
<html>
<head>
<title>这是一个网页</title>
<link rel="stylesheet" type="text/css" href="">
</head>
<body>
<p>Hello Javascript</p>
<script type='text/javascript' src=''>
//创建节点
var script = document.creatElement('script');
//添加路径
script.src = '...';
//插入到head标签中
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</body>
</html>
我们还可以对其进行封装。
<scirpt>
元素接收完成时会触发一个load
事件,因此可以监听脚本加载时的状态。
IE支持另一个触发事件onreadystatechange
事件,<script>
元素提供一个readyState
属性,该属性有五种状态:
-
uninitialized:
初始状态 -
loading:
开始下载 -
loaded:
下载完成 -
interactive:
数据玩完成下载但不可用 -
complete:
所有数据都已准备就绪
/**
* 动态创建script标签
* @param{路径} src
* @param{回调函数} callback
*/
function scriptLoad(src, callback){
var scritp = document.creatElement('script');
if(script.readyState) {
//IE
script.onreadystatechange = function (){
/**IE在标识最终状态的readyState的值时并不一致,有时达到loaded后就不会达到complate,
又有时,不经过loaded就达到complete,所以这两个值一起检测最好
*/
if(scritp.readyState == 'loaded' || script.readyState == 'complete'){
//两个状态只要有个触发就删除事件监听,保证不触发两次
scritp.onreadystatechang = null;
//执行回调
callback();
}
}
}else{
//其他类型的浏览器
script.onload = function () {
callback();
}
}
script.src = src;
document.head.appendChild(script);
}
注意:由于动态脚本节点下载文件时,返回的代码通常会自动执行,所以当使用动态加载供其他脚本调用的接口脚本时,就会有问题。
6. 脚本注入
通过XMLHttpRequest
对象获取脚本注入页面之中
var xhr = new XMLHttpRequest();
xhr.open('get','路径',true);
xhr.onreadystatechang = function (e) {
if(xhr.status >= 200 && xhr.status < 300 || xhr == 304){
var scsript = docment.creatElement('script');
script.text = xhr.requestText;
document.head.appendChild(script);
}
}
注意:该方法请求的页面和文件必须处于同一个域。
推荐方法
在HTML
文档最后,用内联代码写好其他代码的请求方法,然后执行内联代码让其加载其他所需脚本文件。
总结
1.将script
标签放置于HTML
文档最后。
2.合并脚本,减少HTML
中标签的数量。
3.动态加载脚本,此方法一定要注意加载顺序。
4.XMLHttpRequest对象注入,文件和页面一定要处于同一个域下。