引言
目前项目中的前端架构采用的是RequireJS+AngularJS,小编在工作之余对这个前端框架比较感兴趣,在开始的时候对这个框架不是很懂,因为里面有很多平台自己封装的东西,所以在理解起来不是很容易,经过这一段时间在项目中的运用有了一定的理解,下面先来总结总结一下其中的一个技术点——RequireJS的基本用法。
基本介绍
RequireJS是一个JavaScript文件或者模块的加载器。它可以提高JavaScript文件的加载速度,避免不必要的堵塞。它针对于在浏览器环境中使用做过专门的优化,但它也可以在其他的JavaScript环境中使用,像Node.js一样可以在服务器上运行。说了这么多废话,其实它为我们提供了两种思路解决大量加载js文件带来的问题:
1、模块化组织JS
2、异步加载js文件
为什么需要用RequireJS?
当我们业务比较负载时候我们有时候需要在一个页面中引入大量的js文件,之前的ITOO中会见到一个页面引入了很多的js文件,原先我们的写法是这样的:
<script src="js/app/a.js"></script> <script src="js/app/b.js"></script> <script src="js/app/c.js"></script>
这样写的有很多的缺点:
1、页面在加载的时候从上往下开始加载和渲染的,当页面有很多分散的JS文件的时候,页面会先加载和解析头部的js文件(同步加载),此时页面渲染就被堵塞了,如果这些js文件请求的数量比多,那么网页失去响应的时间就会加长。
2、如果js文件之间是有相互依赖关系的,那么我们的js文件引入的顺序需要我们一定要注意,依赖性大的文件一定在最后引入,但是当依赖关系非常复杂的时候,代码的编写和维护就非常复杂了。
然上面引入JS时候,对于第1点:首先:我们可以放在底部去加载,把所有JS放在</body>之前去,这样就会解决了游览器堵塞的问题,其次我们可以把所有的JS文件打包成一个JS文件,但是依赖性(也就是顺序)我们还是没有办法解决掉,所以我们引入了requireJS(优点:1、实现JS文件的异步加载,避免网页被堵塞。2、管理模块之间的依赖性,便于代码的编写和维护。)。
requireJS的基本语法及用法
1、在官网上下载requireJS包,在我们页面的头部引入require.js文件,基本用法如下:
<head> <meta charset="UTF-8"> <title>RequirJS测试</title> <script src="RequireJS/require.js" defer async="true" data-main="RequireJS/app.js"></script> </head>
sync属性表明文件需要异步加载,IE不支持这个属性,只支持defer,所以上面把这2个属性都加上。接下来,看看requireJS启动加载脚本的初始化方式,requireJS支持属性 data-main 这个属性来加载初始化的JS文件,其中app.js文件也即是我们的入口(主)文件,如果我们的app.js文件的内容为空的话,加载顺序如下:
定义模块文件
首先看一个Demo的目录结构(webstorm开发):
RequireJS编写模块不同于其他脚本文件,它良好的使用define来定义一个作用域避免全局空间污染,它可以显示出其依赖关系,并以函数(定义此模块的那个函数)参数的形式将这些依赖进行注入。大家如果对JS中的闭包比较熟悉的话,这个东西非常的好理解,因为在我看来它就是解决js闭包解决的问题。
b.js中我们写一个简单例子:
/** * Created by zhenghao on 2016/7/4. */ define(function(){ var add = function(x,y) { return x + y; }; return { add : add } });
在入口文件app.js中写入一下内容:
/** * Created by zhenghao on 2016/7/4. */ require(['app/b'], function (m){ console.log(m.add(1,3)); });
我们会在浏览器的console界面看到输入4,说明我们调用成功了,我们来看一下加载顺序:
当然我们也可以编写简单的键值对直接返回一个对象,从而解决全局变量的问题,如下:
a.js文件的内容:
/** * Created by zhenghao on 2016/7/4. */ define(function () { return { color: "black", size: "unisize" } });
app.js初始化文件:
require(['app/a'], function (m){ console.log(m); });
运行结果:
直接返回一个对象,通过使用上面的方法我们可以想到可以解决全局变量概念,比如全局变量全部使用define函数包围,什么时候需要全局变量的话,直接require([‘XX’],function(XX){})这样调用下,同时所有的JS都是异步的,并不会堵塞加载。