requireJs可以解决文件依赖加载问题,例如 JS1依赖于JS2,JS2依赖JS3,JS3依赖JS4,文件加载就应该是 JS4 JS3 JS2 JS1。但是我只想使用JS1中的函数,其他的我不想管,就用到了requireJS 按需加载,我只需要加载JS1,其他的都交给require来做。
用法:
举一个栗子 我要做一个给数组排序的功能,一个HTML,一个test.js,一个sort.js(给JS排序),一个isarr.js(判断传入的参数是否为数组),给一个数组排序首先要判断传入的参数是否为数组,如果为数组进行排序,否则返回错误信息。
HTML
<script src="js/require.js" data-main="js/test"></script> // data-main 为requireJs 的依赖文件入口 H5规定自定义属性最好以‘date-’开头
//test.js
require(['sort'],function(sort) { var arr = [1,4,8,11,25]; console.log(sort(arr)); })
//sort.js
define(['isarr'],function(isArr){ // ‘isarr’(蓝色) 为sort 依赖文件。 isArr(黄色)为导入的isArr,虽然可以随便写,但是最好和依赖文件函数保持一致 function sort(arr) { if (isArr(arr)) { return arr.sort(function(a,b) { return a - b; //数组排序 }) }else{ return "传入的参数不是数组"; } } return sort; })
//isarr.js
define(function() { function isArr(arr) { if(arr.constructor == Array && arr instanceof Array){ /*判断arr是否为数组 *1. typeof arr 返回值的是Object 而不是Array 所以无法判断 *2. arr.constructor(构造函数或叫构造器),能找到arr数组的构造函数是Array 没有引 号“” *3. arr instanceof Array 可以判断数组类型 */ return true; } return false; } return IsArr; })
原理:
既然文件加载有效,那requireJS是怎么实现加载的呢? 我们打开工具发现body中并没有多出<script>标签,但是在<head>中发现了我们依赖的两个JS文件,requireJS是怎么加载的呢?
其中一个<script>
<script type="text/javascript" charset="utf-8" async="" data-requirecontext="_" data-requiremodule="sort" src="js/sort.js"></script>
requireJS加载的文件比我们自己写的文件多出了三个属性 async,data-requirecontent和data-requiremodule。
其中data-requiremodule指向的是需要加载的模块。
1.async 和 defer
而async是一种异步加载。 异步加载有两种,defer和async。下图是正常加载和defer异步加载与async异步加载的解析加载对比
正常加载是 解析HTML 遇见了JS 就去下载然后立刻执行
defer 异步加载是解析HTML遇见JS,异步的去下载JS,在最后去执行。所以defer加载从理论上能保证JS文件的加载顺序。
async 异步加载是解析HTML遇见JS,异步去下载JS,然后立刻执行。所以async不一定能保证JS文件加载顺序。如果JS文件比较小的情况下可能后被加载先执行。
defer和async的区别是什么呢? defer是IE提出的语法,async是标准浏览器提出的语法。兼容性问题不太一样,功能也不一样。他们都叫Js的异步加载都会增加浏览器对JS的加载速度。
如果文件增加了async或者defer,文件里是不能够写document.write(),会报错
2. AMD和CMD
AMD(Asynchronous Module Define) 异步模块化定义
CMD(Common Module Define) 通用模块化定义
其实模块化开发框架不只有requireJS 还有一个seaJS 这个框架是一个阿里程序员玉伯开发的。
其中seaJS的写法为
//seaJS 写法 define(function(require) { var arr = [1,4,8,11,25]; //此处省略100行业务逻辑 var sort = require('sort');//导入依赖的排序函数 console.log(sort(arr)); }) //requireJS require(['sort'],function(sort) { var arr = [1,4,8,11,25]; //此处省略100行业务逻辑 console.log(sort(arr)); })
观察以上两种写法,
第一种写法是依赖就近,就是你写了很多很多业务逻辑,等你想用的时候再加载依赖的方法。先声明后加载。
第二种写法是依赖前置,就是不管你什么时候用这个方法,声明require时就要把依赖的方法加载进来。先声明先加载。
其中SeaJS的写法在requireJS-2.0版本也支持。
在百度上搜索 ’AMD CMD的区别‘ 在知乎上,seaJS的作者玉伯给出了非常明确的答案