HTML5学习笔记(二十三):DOM应用之动态加载脚本
同步加载和执行JS的情况
在HTML页面的</body>表情之前添加的所有<script>标签,无论是直接嵌入JS代码还是引入外部js代码都是同步执行的,这里的同步执行指的是在加载好和执行完JS代码之前整个浏览器的界面都是阻塞的。
静态加载时
内嵌代码和引入js代码都是同步加载。
动态加载时
通过document.write('<script src="xxx.js"></script>');的方式加入的代码也是同步加载的,但是要注意一点,这里开始加载和解析xxx.js是在执行完成当前的<script>标签之后,所以下面的代码会报错(我们假设test.js中创建了全局的p对象,且该对象存在sayHi的方法):
<script>
console.log("sync load js");
document.write('<script src="test.js"></script>');
console.log(p.sayHi());
</script>
根据我们说的开始加载和解析xxx.js是在执行完成当前的<script>标签之后,可以把上面的代码转换如下:
<script>
console.log("sync load js");
console.log(p.sayHi());
</script>
<script src="test.js"></script>
这样必然会出错,如下则可以正常执行:
<script>
console.log("sync load js");
document.write('<script src="test.js"></script>');
</script>
<script>
console.log(p.sayHi());
</script>
document.write方式同步加载外部js文件无论是内嵌的写法还是写在外部js文件中,效果都是一样的,都会同步加载和执行。
异步加载和执行JS的情况
静态加载时
对于内嵌的JS代码只能同步执行,对于通过<script>标签引入的外部js文件,可以通过设定defer和async两个属性改变为异步加载执行。
defer
代码如下:<script src="xxx.js" defer></script>,该属性在HTML4.01引入,告诉浏览器立即下载该脚本(下载期间不阻塞页面),但是等待遇到</html>标签之后再执行,同时执行顺序按照标签出现顺序进行执行。该脚本的执行一定会在页面的load事件之前。
async
代码如下:<script src="xxx.js" async></script>,该属性在HTML5引入,告诉浏览器立即下载该脚本(下载期间不阻塞页面),但是执行脚本时不能保证按照标签出现顺序执行。该脚本的执行一定会在页面的load事件之前。
最佳实践
由于浏览器的支持不同,所以最好的方法仍然是将<script src="xxx.js"></script>脚本放在页面的最下方引入。
动态加载时
如果我们希望在页面任意时刻动态异步加载js文件,可以通过使用DOM元素创建方法来实现:
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "xxx.js";
document.getElementsByTagName("head")[0].appendChild(script);
当script元素被添加到页面之后便开始下载脚本文件。该技术的优点是:无论在何处启动下载,文件的下载和运行都不会阻塞其他页面处理过程。当script文件下载完成后,返回的代码通常被立即执行(除了FF和Opera,它们将等待此前的所有动态脚本节点执行完毕。)
唯一的问题是我们需要知道动态加载的脚本何时完成加载并可以使用,FF, Opera, Chrome和Safari3+会在节点接收完成后发出一个load事件;IE则是发出一个readystatechange事件,<script>元素有一个readyState属性,它的值随着下载过程而改变。readyState有5种取值:uninitialized(默认状态),loading(下载开始),loaded(下载完成),interactive(下载完成但尚不可用),complete(所有数据已准备好)。
最终的代码如下:
function loadScript(url, callback){
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState) { // IE
script.onreadystatechange = function() {
if (script.readyState == "loaded" || script.readyState == "complete") {
script.onreadystatechange = null;
callback();
}
};
} else { // FF, Chrome, Opera, ...
script.onload = function() {
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
如果要加载多个文件,并且要保证顺序,则可以采用将上述函数串联的方式实现。
loadScript("../scripts/test1.js", function(){
loadScript("../scripts/test2.js", function(){
loadScript("../scripts/test3.js", function(){
test3.print("hi, i'm abc.");
})
});
});
如果觉得这种嵌入的写法太不爽,也可以稍作修改改为Promise的写法。
HTML5学习笔记(二十三):DOM应用之动态加载脚本的更多相关文章
- AntDesign vue学习笔记(五)导航菜单动态加载
一般的后台系统都有一个树形导航菜单,具体实现如下,主要参考https://my.oschina.net/u/4131669/blog/3048416 "menuList": [ { ...
- python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码
python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码 淘宝IP地址库 http://ip.taobao.com/目前提供的服务包括:1. 根据用户提供的 ...
- Android 学习笔记之Volley(七)实现Json数据加载和解析...
学习内容: 1.使用Volley实现异步加载Json数据... Volley的第二大请求就是通过发送请求异步实现Json数据信息的加载,加载Json数据有两种方式,一种是通过获取Json对象,然后 ...
- Redis深入学习笔记(一)Redis启动数据加载流程
这两年使用Redis从单节点到主备,从主备到一主多从,再到现在使用集群,碰到很多坑,所以决定深入学习下Redis工作原理并予以记录. 本系列主要记录了Redis工作原理的一些要点,当然配置搭建和使用这 ...
- Ext JS学习第十天 Ext基础之动态加载JS文件(补充)
此文用来记录学习笔记: •Ext4.x版本提供的一大亮点就是Ext.Loader这个类的动态加载机制!只要遵循路径规范,即可动态加载js文件,方便把自己扩展组件动态加载进来,并且减轻浏览器的压力. • ...
- Javascript学习笔记二——操作DOM
Javascript学习笔记 DOM操作: 一.GetElementById() ID在HTML是唯一的,getElementById()可以定位唯一的一个DOM节点 二.querySelector( ...
- (C/C++学习笔记) 二十三. 运行时类型识别
二十三. 运行时类型识别 ● 定义 运行时类型识别(Run-time Type Identification, RTTI) 通过RTTI, 程序能够使用基类的指针或引用来检查(check)这些指针或引 ...
- Java基础学习笔记二十三 Java核心语法之反射
类加载器 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,链接,初始化三步来实现对这个类进行初始化. 加载就是指将class文件读入内存,并为之创建一个Class对象.任 ...
- Windows调试学习笔记:(一)WinDBG中加载SOS和CLR
最近产品环境出现了部分服务器当机情况,虽然重启之后问题就不出现了.但本着彻底解决问题的态度,想要找到root cause.多次尝试Visual Studio失败(可能是代码惊醒了优化和签名)之后,决定 ...
随机推荐
- 【树莓派+.NET MF打造视频监控智能车】遥控篇
树莓派是最近比较火热的开源硬件,其设备只有信用卡大小,运行着Linux系统,专为学生编程教育而设计.我十多年的技术路线基本以学习微软的技术为主,中间也曾试图学习过linux,但是相对陡峭的学习曲线,只 ...
- django之创建第4-1个项目-访问dict数据
1.修改index.html文件 <!DOCTYPE html> <html lang="en"> <head> <meta charse ...
- PLSQL Developer启动失败
原因:和打印服务冲突 禁掉打印服务,不过打印功能是不行了
- (原+译)使用numpy.savez保存字典后读取的问题
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/7608928.html 参考网址; https://stackoverflow.com/question ...
- 使用Thrift让Python为Java提供服务
Thrift是基于TCP的,谷歌的GRPC是基于HTTP的.Thrift和GRPC都是比直接写个web接口进行调用更完美的方式,最明显的一点就是:我们可以定义结构体,避免了手动解析的过程. 但是,在将 ...
- 使用Java调用JS
import junit.framework.TestCase; import javax.script.ScriptEngine; import javax.script.ScriptEngineM ...
- maven-compiler-plugin升级到3.1出现问题(转)
转自:http://my.oschina.net/zhuka/blog/124503 No compiler is provided in this environment. Perhaps you ...
- 在 iOS 中实现方法链调用
编译:伯乐在线 - 林欣达 如有好文章投稿,请点击 → 这里了解详情 如需转载,发送「转载」二字查看说明 前言 链式调用(chained calls)是指在函数调用返回了一个对象的时候,使得这个调用链 ...
- Ubuntu中恢复rm命令误删文件(转)
计算机系统:Ubuntu 16.04 1 背景 在做项目的时候,本来想使用rm命令删除以14开头的文件,结果写成如下形式: rm 14 * 注意,本来14和*之间不应该有空格的,但是误写了一个空格,结 ...
- 必须掌握的30种SQL语句优化
1.’对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用 ...