引言

目前项目中的前端架构采用的是RequireJS+AngularJS,小编在工作之余对这个前端框架比较感兴趣,在开始的

时候对这个框架不是很懂,因为里面有很多平台自己封装的东西,所以在理解起来不是很容易,经过这一段时间在项

目中的运用有了一定的理解,下面先来总结总结一下其中的一个技术点——RequireJS的基本用法。

基本介绍

RequireJS是一个JavaScript文件或者模块的加载器。它可以提高JavaScript文件的加载速度,避免不必要的

堵塞。它针对于在浏览器环境中使用做过专门的优化,但它也可以在其他的JavaScript环境中使用,像Node.js一样

可以在服务器上运行。说了这么多废话,其实它为我们提供了两种思路解决大量加载js文件带来的问题:

1、模块化组织JS

2、异步加载js文件

为什么需要用RequireJS?

当我们业务比较负载时候我们有时候需要在一个页面中引入大量的js文件,之前的ITOO中会见到一个页面引入

了很多的js文件,原先我们的写法是这样的:

  1. <script src="js/app/a.js"></script>

  2. <script src="js/app/b.js"></script>

  3. <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文件,基本用法如下:

  1. <head>

  2. <meta charset="UTF-8">

  3. <title>RequirJS测试</title>

  4. <script src="RequireJS/require.js" defer async="true" data-main="RequireJS/app.js"></script>

  5. </head>

sync属性表明文件需要异步加载,IE不支持这个属性,只支持defer,所以上面把这2个属性都加上。接下来,看

看requireJS启动加载脚本的初始化方式,requireJS支持属性 data-main 这个属性来加载初始化的JS文件,其中

app.js文件也即是我们的入口(主)文件,如果我们的app.js文件的内容为空的话,加载顺序如下:

定义模块文件

首先看一个Demo的目录结构(webstorm开发):

RequireJS编写模块不同于其他脚本文件,它良好的使用define来定义一个作用域避免全局空间污染,它可以显

示出其依赖关系,并以函数(定义此模块的那个函数)参数的形式将这些依赖进行注入。大家如果对JS中的闭包比较熟

悉的话,这个东西非常的好理解,因为在我看来它就是解决js闭包解决的问题。

b.js中我们写一个简单例子:

  1. /**

  2. * Created by zhenghao on 2016/7/4.

  3. */

  4. define(function(){

  5. var add = function(x,y) {

  6. return x + y;

  7. };

  8. return {

  9. add : add

  10. }

  11. });

在入口文件app.js中写入一下内容:

  1. /**

  2. * Created by zhenghao on 2016/7/4.

  3. */

  4. require(['app/b'], function (m){

  5. console.log(m.add(1,3));

  6. });

我们会在浏览器的console界面看到输入4,说明我们调用成功了,我们来看一下加载顺序:

当然我们也可以编写简单的键值对直接返回一个对象,从而解决全局变量的问题,如下:

a.js文件的内容:

  1. /**

  2. * Created by zhenghao on 2016/7/4.

  3. */

  4. define(function () {

  5. return {

  6. color: "black",

  7. size: "unisize"

  8. }

  9. });

app.js初始化文件:

  1. require(['app/a'], function (m){

  2. console.log(m);

  3. });

运行结果:

直接返回一个对象,通过使用上面的方法我们可以想到可以解决全局变量概念,比如全局变量全部使用define函数

包围,什么时候需要全局变量的话,直接require([‘XX’],function(XX){})这样调用下,同时所有的JS都是异步

的,并不会堵塞加载。

requireJS配置项介绍

1、baseUrl:指定本地模块的基准目录,即本地模块的路径是相对于那个目录的,该属性通常有requireJS加载

时的data-main属性指定。比如如下代码

<script src="RequireJS/require.js" defer async="true" data-main="RequireJS/app.js"></script>

app.js文件的内容:

  1. requirejs.config({

  2. baseUrl: 'RequireJS/app'

  3. });

  4. requirejs(['a','b','c'],function(a,b,c){

  5. });

我们在浏览器中看到如下请求路径:

如上可以看到,View.html和RequireJS是同一个目录下的,都是放在requireJS文件夹里面的,所以定义

baseUrl:’RequireJS/app’ 会自动解析成 requireJSService/RequireJS/app/ 所以

requirejs([‘a’,’b’,’c’])的话,会自动到requireJSService/RequireJS/app/目录下去查找a.js,b.js,

c.js.找到了就可以加载出来.

如果未显示设置baseUrl,则默认值是加载require.js的html所处的位置,如果使用了data-main属性的话,则该

路径变成了baseUrl.如下代码:

<span style="font-size:18px;"><script src="RequireJS/require.js" defer async="true" data-main="RequireJS/app.js"></script></span>

app.js文件的内容:

  1. requirejs(['a','b','c'],function(a,b,c){

  2. });

如上显示:默认情况下是从data-main文件入口去加载RequireJS/app.js代码的,但是现在app.js中并没有设置

config配置项,所以使用requirejs([‘a’,’b’,’c’],function(a,b,c))的时候会继续加载RequireJS下面的

a.js,b.js,c.js,如果找到就加载,没有找到就显示404 not found,如上所示。

2、path:paths是映射那些不直接放在baseUrl指定的目录下的文件,设置paths的起始位置是相对于baseUrl

的,除非该path设置是以”/”开头或含有URL协议(http://或者https://).

app.js文件的内容如下:

  1. requirejs.config({

  2. baseUrl: 'RequireJS/lib',

  3. paths: {

  4. app: '../app'

  5. }

  6. });

  7. requirejs(['app/a'],function(a){

  8. });

可以看到paths是相对于baseUrl配置项生成的,baseUrl:’RequireJS/lib’下的所有js文件,但是paths下的

app:’../app’是相对于js/lib下设置的,’..’的解析到js目录下,然后就解析成RequireJS/app下,再

require([‘app/a’]),就解析到RequireJS/app/a.js了。

当我们把baseUrl注释掉的话,a.js可定就找不到了,此时加载的路径如下:

  1. requirejs.config({

  2. //baseUrl: 'RequireJS/lib',

  3. paths: {

  4. app: '../app'

  5. }

  6. });

  7. requirejs(['app/a'],function(a){

  8. })

3、skim参数:理论上,require.js加载的模块,必须是按照AMD规范、用define()函数定义的模块。但是实际

上,虽然已经有一部分流行的函数库(比如jQuery)符合AMD规范,更多的库并不符合,而skim解决了使用非AMD方式

定义的模块(如jquery插件)及其载入顺序,为那些没有使用define()来声明依赖关系,设置模块的”浏览器全局变量

注入”型脚本做依赖和导出配置。

app.js中的代码如下:

  1. require.config({

  2. baseUrl: 'RequireJS/lib',

  3. paths: {

  4. 'app': '../app',

  5. 'temp':'../app/depBase',

  6. 'jquery':'../lib/jquery-1.7.1',

  7. 'a':'../app/a'

  8. },

  9. shim: {

  10. 'temp': { exports:'_',deps: ['jquery'] }

  11. }

  12. });

  13. require(['temp','a'],function(base){

  14. console.log(base);

  15. });

文件加载顺序及加载结果

require.config()接受一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用

来配置不兼容的模块。具体来说,每个模块要定义(1)exports值(输出的变量名),表明这个模块外部调用时的名

称;(2)deps数组,表明该模块的依赖性。

4、map参数:对于给定的模块前缀,使用一个不同的模块ID来加载该模块。这个手段在大型项目中是非常重要

的,比如我们不同的模块需要加载不同版本的jquery文件,这就需要我们用到这个map来给我们解决了,比如我们

a.js文件需要依赖jquery-1.7.1,而我们的b.js文件需要依赖jquery-1.8.0。请看下面例子:

app.js文件中的代码:

  1. requirejs.config({

  2. map: {

  3. 'app/a': {

  4. 'jquery': 'RequireJS/lib/jquery-1.7.1.js'

  5. },

  6. 'app/b': {

  7. 'jquery': 'RequireJS/lib/jquery-1.8.0.min.js'

  8. }

  9. }

  10. });

  11. /*require(['app/a'],function(jq){

  12. });*/

  13. require(['app/b'],function(jq){

  14. });

a.js文件和b.js文件中的内容如下:

  1. define(function (require, exports, module) {

  2. var a = require(['jquery']);

  3. });

  1. define(function (require, exports, module) {

  2. var b = require(['jquery']);

  3. });

我们只加载b.js文件的时候的文件加载结果:

如果我们只加载a.js文件,那么我们会看到加载的是jquery-1.7.1.js文件。

5.config参数:这个和我们c#中的配置文件一样,我们一般将易变的或者application级别的信息配置在

config里面,同样这个东西在requireJS中也是支持的,但是这就需要我们提供一种手段将里面的配置的信息传递到

每一个模块中,基于requirejs.config()的config配置项来实现。要获取这些信息的模块可以加载特殊的依

赖 ”moudle” ,并调用module.config().

app.js文件中的代码:

  1. requirejs.config({

  2. config: {

  3. 'app/c': {

  4. name: '郑浩'

  5. },

  6. 'app/d': {

  7. age: 18

  8. }

  9. }

  10. });

  11. require(['app/c'],function(c){

  12. console.log(c);

  13. });

  14. require(['app/d'],function(d){

  15. console.log(d);

  16. });

c.js文件和d.js文件中的代码如下:

  1. define(function (require, exports, module) {

  2. //其值是'郑浩'

  3. var size = module.config().name;

  4. return size;

  5. });

  1. <span style="font-family:SimSun;font-size:18px;">define(['module'], function (module) {

  2. var color = module.config().age;

  3. return color;

  4. });</span>

最后赠送

其实require和我们之前过的ajax或者$http有类似地方就是在回调函数上面,当我们在加载出错的时候会走第二个

回调函数,代码如下:

  1. require(['b'], function ($) {

  2. //Do something with $ here

  3. }, function (err) {

  4. alert(err)

  5. });

小结

以上就是小编对requireJS的一些理解和总结,其中的例子都是对现在项目中一个缩影,上面讲解的一些属性和

参数都在我们项目中出现过,也是我们在使用requireJS经常用到的一些基本知识,里面有一些东西还不是很明白,

需要在项目中继续学习和研究,希望对读者有些帮助

requireJS的基本用法相关推荐

  1. grunt 打包前端代码

    [grunt整合版]30分钟学会使用grunt打包前端代码 grunt 是一套前端自动化工具,一个基于nodeJs的命令行工具,一般用于: ① 压缩文件 ② 合并文件 ③ 简单语法检查 对于其他用法, ...

  2. 【grunt整合版】30分钟学会使用grunt打包前端代码

    grunt 是一套前端自动化工具,一个基于nodeJs的命令行工具,一般用于: ① 压缩文件 ② 合并文件 ③ 简单语法检查 对于其他用法,我还不太清楚,我们这里简单介绍下grunt的压缩.合并文件, ...

  3. JavaScript大杂烩17 - 性能优化

    在上一节推荐实践中其实很多方面是与效率有关的,但那些都是语言层次的优化,这一节偏重学习大的方面的优化,比如JavaScript脚本的组织,加载,压缩等等. 当然在此之前,分析一下浏览器的特征还是很有意 ...

  4. requireJS用法

    一份超详细的requireJS用法 转载于http://www.php.cn/js-tutorial-392533.html requireJS 可以很轻易的将一个项目中的JavaScript代码分割 ...

  5. requirejs的用法

    一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载.下面的网页代 ...

  6. requireJS常用用法

    为什么使用requirejs? 1.异步加载文件: 2.模块化开发:一个文件即是一个模块,减少全局变量. 相关方法 1.define()定义模块 define('moduleName可选', [依赖的 ...

  7. requirejs 用法

    一.实现功能 1.jquery 能访问 2.引用第三方cdn 3.js访问不了,加载备用js 4.访问自定义函数 5.异步加载写法 6.加载非AMD规范的JS文件 7.不同文件引用不同版本的js 8. ...

  8. requirejs的用法(二)

    这个系列的第一部分和第二部分,介绍了Javascript模块原型和理论概念,今天介绍如何将它们用于实战. 我采用的是一个非常流行的库require.js. 一.为什么要用require.js? 最早的 ...

  9. RequireJS - 用法

    首页在html页面中写入: <script src="js/require.js" data-main="js/main"></script& ...

最新文章

  1. php判断数组不重复的元素,php从数组中随机选择若干不重复元素
  2. [转]常见的动态规划问题分析与求解
  3. Python 中的hash
  4. img title属性值利用#13换行
  5. WWW 2022 | 弯道超车:基于纯MLP架构的序列推荐模型
  6. BIOS——PE无法识别硬盘问题问题解决方案
  7. boost::fusion::joint_view用法的测试程序
  8. 瑞斯康达nms_瑞斯康达接入网设备维护手册免费.pdf
  9. Spark写入MySQL报错乱码+报错
  10. Python网路请求(GET示例)
  11. vb html ie弹出窗口,VB6 统制IE弹出模式窗口
  12. mysql 直方图_MySQL直方图
  13. dudu注意:这个可能是bug吧?
  14. MySQL中exists和in的区别
  15. Mac版的DjVu格式文件阅读工具
  16. 2022.5.6 java标识符
  17. 利用 adb 对手机进行屏幕分辨率设置
  18. 计算机英语rom是什么意思,涨姿势!电脑里的rom,ram是什么意思?
  19. python上方菜单栏不见了如何恢复_word菜单栏不见了,如何恢复
  20. 清华大学尹成 怎么样

热门文章

  1. 基于Matlab的MIMO通信系统仿真
  2. 三轴陀螺仪 偏置稳定性 光纤陀螺 光纤陀螺仪 光纤陀螺惯性导航系统 光纤陀螺惯性测量单元 六自由度IMU 单轴激光陀螺仪 双天线组合导航系统 双轴精确陀螺仪 导航级FOG怎么选择?
  3. java引用和指针的区别
  4. Composer 基本使用方法
  5. xshell删除文件夹命令_XShell常用命令
  6. Navicat12 过期了怎么办
  7. 关于“知乎治校”的调研
  8. citra黑屏_citra模拟器下载|citra 3ds模拟器2017下载(解决黑屏问题) v3.1 x64/x32版_数码资源网...
  9. IIS发布网站进行访问时提示权限不足的简单解决方法
  10. 小猫爪:PMSM之FOC控制02-Park变换