跳简单组织AngularJS模块。一篇稿子掌握RequireJS常因此知识,一首掌握requirejs

去年下半年接触前端开发和AngularJS,一路暴跌跌撞撞,尤以模块化代码组织的训太深。

同样首文章掌握RequireJS常因此文化,一篇掌握requirejs

本文采取渐进的点子,从理论及实施,从RequireJS官方API文档中,总结发生以用RequireJS过程被极其常用之一部分据此法,并针对文档中不够明晰具体的情节,加以例证和分析,分享给大家供大家参考,具体内容如下

1. 模块化
信任每个前端开发人员在刚刚开头接触js编程时,都写过类似下面这样风格的代码:

<script type="text/javascript">
  var a = 1;
  var b = 2;
  var c = a * a + b * b;

  if(c> 1) {
    alert('c > 1');
  }

  function add(a, b) {
    return a + b;
  }

  c = add(a,b);
</script>

<a href="javascript:;" onclick="click(this);" title="">请点击</a>

这些代码的性状是:

  • 各处可见的全局变量
  • 大气底函数
  • 内嵌在html元素上的各种js调用

本来这些代码本身在促成效益上连不曾不当,但是由代码的而重用性,健壮性以及可维护性来说,这种编程方式是有问题之,尤其是在页面逻辑较为复杂的动中,这些问题会见暴露地特别醒目:

  • 全局变量极容易致命名冲突
  • 函数式编程非常勿便宜代码的社及管制
  • 内嵌的js调用好不便利代码的保安,因为html代码有上是好层和庞大的

故当这些题目出现的下,js大牛们便从头探寻去化解这些题材的究极办法,于是模块化开发就应运而生了。正使模块化这个定义的外部意思同样,它要求在编写代码的当儿,按层次,按职能,将单身的逻辑,封装成可选用的模块,对外提供直接明了之调用接口,内部贯彻细节了私有,并且模块之间的里边贯彻以执行中互不干扰,最终的结果就是足以缓解眼前举例提到的题材。一个概括按照模块化开发要求编制的例子:

//module.js
var student = function (name) {
    return name && {
        getName: function () {
          return name;
        }
      };
  },
  course = function (name) {
    return name && {
        getName: function () {
          return name;
        }
      }
  },
  controller = function () {
    var data = {};
    return {
      add: function (stu, cour) {
        var stuName = stu && stu.getName(),
          courName = cour && cour.getName(),
          current,
          _filter = function (e) {
            return e === courName;
          };

        if (!stuName || !courName) return;

        current = data[stuName] = data[stuName] || [];

        if (current.filter(_filter).length === 0) {
          current.push(courName);
        }
      },
      list: function (stu) {
        var stuName = stu && stu.getName(),
          current = data[stuName];
        current && console.log(current.join(';'));
      }
    }
  };

//main.js

var stu = new student('lyzg'),
  c = new controller();

c.add(stu,new course('javascript'));
c.add(stu,new course('html'));
c.add(stu,new course('css'));
c.list(stu);

如上代码定义了三个模块分别代表学生,课程和控制器,然后于main.js中调用了controller提供的add和list接口,为lyzg这个学生上加了三派系学科,然后于控制台显示了出来。运行结果如下:

javascript;html;css

经上例,可以观看模块化的代码结构和逻辑很鲜明,代码看起颇优雅,另外由于逻辑都经模块拆分,所以上了解耦的目的,代码的力量也会见比健康。不过上例使用的这种模块化开发方为并无是没有问题,这个问题虽是它还是把模块引用如student这些一直长到了全局空间下,虽然经模块减少了累累大局空间的变量和函数,但是模块引用我要要乘全局空间,才能够给调用,当模块于多,或者发引入第三正模块库时,仍然可能导致命名冲突之题材,所以这种全局空间下的模块化开发的法并无是无比完美的道。目前常见的模块化开发方式,全局空间法是最好基本的相同栽,另外常见的还有遵循AMD规范的开发方式,遵循CMD规范的开发方式,和ECMAScript
6的开发方式。需要征的凡,CMD和ES6暨本文的中坚没有关联,所以无会见以此介绍,后面的情节要介绍AMD以及落实了AMD规范的RequireJS。

2. AMD规范
凑巧而上文提到,实现模块化开发的计,另外常见的相同栽不畏是遵循AMD规范之兑现方式,不过AMD规范并无是具体的落实方式,而仅是模块化开发之一律种缓解方案,你得拿它们掌握成模块化开发的有接口声明,如果您要是促成一个依照该专业的模块化开发工具,就非得兑现它预先定义的API。比如其要求以加载模块时,必须用如下的API调用方式:

require([module], callback)
其中:
[module]:是一个数组,里面的成员就是要加载的模块;
callback:是模块加载完成之后的回调函数

富有遵循AMD规范之模块化工具,都要随其的要求去实现,比如RequireJS这个库房,就是完全遵循AMD规范落实之,所以当使用RequireJS加载或者调用模块时,如果你先知情AMD规范的话,你虽掌握该怎么用RequireJS了。规范之补在叫,不同的贯彻可出同等的调用方式,很轻切换不同之工具使用,至于实际用啊一个兑现,这就是同各个工具的分级的长和项目之特征发生涉及,这些还是在路上马选型的上用确定的。目前RequireJS不是唯一兑现了AMD规范之堆栈,像Dojo这种还完美的js库也还发AMD的兑现。

最终对AMD全称做一个说明,译为:异步模块定义。异步强调的凡,在加载模块和模块所依靠的旁模块时,都运异步加载的方法,避免模块加载阻塞了网页的渲染进度。相比传统的异步加载,AMD工具的异步加载更加简便易行,而且还能促成准需加载,具体讲以生有些证明。

3. JavaScript之异步加载与本需要加载 html中之script标签在加载与履行过程被见面死网页的渲染,所以一般要求尽量以script标签放置于body元素的脚,以便加速页面显示的快,还有平等栽方式就是是透过异步加载的点子来加以载js,这样好免js文件对html渲染之梗塞。

第1种异步加载的方是直动用脚本生成script标签的道:

(function() {
  var s = document.createElement('script');
  s.type = 'text/javascript';
  s.async = true;
  s.src = 'http://yourdomain.com/script.js';
  var x = document.getElementsByTagName('script')[0];
  x.parentNode.insertBefore(s, x);
})();

即段代码,放置于script标记内部,然后该script标记添加到body元素的底色即可。

第2种植方法是依赖script的习性:defer和async,defer这个特性在IE浏览器与朝的火狐浏览器中支持,async在支持html5的浏览器上且支持,只要有应声片独特性,script就见面因异步的方来加载,所以script在html中的岗位就非紧要了:

<script defer async="true" type="text/javascript" src="app/foo.js"></script>
<script defer async="true" type="text/javascript" src="app/bar.js"></script>
<script defer async="true" type="text/javascript" src="app/main.js"></script>

这种方式下,所有异步js在尽之时光还是按顺序执行的,不然就会有因问题,比如要达到例被之main.js依赖foo.js和bar.js,但是main.js先实行的讲话虽会来错了。虽然一向理论及这种措施为算是不磨了,但是不够好,因为它们之所以起来非常烦,而且还闹只问题就是是页面需要丰富多个script标记和无辙了形成随需加载。

JS的以需加载分点儿单层次,第一单层次是就加载是页面可能给用到的JS,第二独层次是以光以采用某个JS的时候才去加载。传统地方式很易好第一独层次,但是不爱形成第二个层次,虽然咱可由此集合和压缩工具,将有页面所有的JS都添加到一个文书被去,最充分程度减少资源请求量,但是这个JS请求到客户端以后,其中有广大情节可能还为此无达到,要是出个器能够好以用的时刻才去加载相关js就完美解决问题了,比如RequireJS。

4. RequireJS时因此用法总结 前文多次提及RequireJS,本有以对准她的常用用法详细说明,它的官方地址是:http://www.requirejs.cn/,你可以到该地址去下载最新版RequireJS文件。RequireJS作为目前使用最广泛的AMD工具,它的主要优点是:

  • 完全支持模块化开发
  • 能用非AMD规范的模块引入到RequireJS中利用
  • 异步加载JS
  • 一齐按需要加载依赖模块,模块文件才待减小混淆,不欲统一
  • 左调试
  • 插件支持

4.01 如何下RequireJS
用方法要命简单,只要一个script标记就可以当网页中加载RequireJS:

<script defer async="true" src="/bower_components/requirejs/require.js"></script>

由这里运用了defer和async这简单只异步加载的特性,所以require.js是异步加载的,你拿这个script标记放置在外地方还未曾问题。

4.02
如何使用RequireJS加载并施行时网页的逻辑JS

4.01化解的才是RequireJS的以问题,但它们不过是一个JS库,是一个给眼前页面的逻辑所祭的工具,真正贯彻网页功能逻辑的是我们设运用RequireJS编写的主JS,这个主JS(假设这些代码都放置于main.js文件被)又欠怎么行使RJ来加载执行也?方式如下:

<script data-main="scripts/main.js" defer async="true" src="/bower_components/requirejs/require.js"></script>

对比4.01,你会意识script标记多了一个data-main,RJ用这布局时页面的主JS,你若管逻辑都写以是main.js里面。当RJ自身加载执行后,就会见另行异步加载main.js。这个main.js是时下网页所有逻辑的输入,理想状态下,整个网页就待就一个script标记,利用RJ加载依赖的别样文件,如jquery等。

 4.03 main.js怎么写
设项目的目录结构为:

图片 1

main.js是跟当前页面相关的主JS,app文件夹存放本项目自定义的模块,lib存放第三方库。

html中本4.02之方配置RJ。main.js的代码如下:

require(['lib/foo', 'app/bar', 'app/app'], function(foo, bar, app) {
  //use foo bar app do sth
});

在当时段JS中,我们下RJ提供的require方法,加载了三独模块,然后以此三个模块都加载成功以后执行页面逻辑。require方法有2单参数,第一只参数是数组类型的,实际采用时,数组的每个元素都是一个模块的module
ID,第二单参数是一个回调函数,这个函数在首先独参数定义的有模块都加载成功后回调,形参的个数和一一分别同第一只参数定义的模块对应,比如第一个模块时lib/foo,那么这回调函数的率先单参数就是foo这个模块的援,在回调函数中我们下这些形参来调用各个模块的法门,由于回调是在列模块加载后才调用的,所以这些模块引用得还是行之。

打以上这大概的代码,你应该早就明白该怎么以RJ了。

4.04 RJ的baseUrl和module ID
以介绍RJ如何去分析依赖之那些模块JS的不二法门时,必须事先动手清楚baseUrl和module
ID这片个概念。

html中之base元素可以定义当前页面内任何http请求的url前缀有,RJ的baseUrl跟此base元素起的来意是相近之,由于RJ总是动态地呼吁依赖的JS文件,所以自然关系到一个JS文件的路解析问题,RJ默认采用同样种baseUrl
+
moduleID的解析方法,这个分析方法持续会举例说明。这个baseUrl非常主要,RJ对其的拍卖遵循如下规则:

  • 以无利用data-main和config的情况下,baseUrl默看眼前页面的目
  • 于产生data-main的情事下,main.js前面的片即使是baseUrl,比如上面的scripts/
  • 每当起config的景下,baseUrl以config配置的啊仍

上述三栽方法,优先级由没有到强排列。

data-main的运方式,你早已知道了,config该怎么布置,如下所示:

require.config({
  baseUrl: 'scripts'
});

其一布局必须放在main.js的极度前方。data-main与config配置同时存在的时光,以config为依照,由于RJ的另配置也是以此职务安排的,所以4.03挨的main.js可以转移化如下结构,以便将来之扩张:

require.config({
  baseUrl: 'scripts'
});

require(['lib/foo', 'app/bar', 'app/app'], function(foo, bar, app) {
  // use foo bar app do sth
});

关于module
ID,就是在require方法与连续之define方法里,用在因数组这个参数里,用来标识一个模块的字符串。上面代码中之[‘lib/foo’,
‘app/bar’, ‘app/app’]不畏是一个仗数组,其中的每个元素都是一个module
ID。值得注意的凡,module ID并不一定是该module
相关JS路径的同一有,有的module
ID很紧缺,但也许路径很丰富,这同RJ的辨析规则有关。下一致节详细介绍。

4.05 RJ的公文分析规则
RJ默认按baseUrl + module
ID的平整,解析文件,并且它默认要加载的文书都是js,所以你的module
ID里面可以无保证含.js的后缀,这虽是吗甚你盼的module ID都是lib/foo,
app/bar这种形式了。有三种module ID,不适用这种规则:

  • 以/开头,如/lib/jquey.js
  • 以.js结尾,如test.js
  • 包含http或https,如**http://xx.baidu.com/js/jquery.js****
    **

如若main.js如下使用:

require.config({
  baseUrl: 'scripts'
});

require(['/lib/foo', 'test.js', '/js/jquery'], function(foo, bar, app) {
  // use foo bar app do sth
});

即时三单module 都非会见依据baseUrl + module ID的规则来分析,而是直接用module
ID来分析,等效为下的代码:

<script src="/lib/foo.js"></script>
<script src="test.js"></script>
<script src="/js/jquery.js"></script>

各种module ID解析举例:

例1,项目布局如下:

图片 2

main.js如下:

require.config({
  baseUrl: 'scripts'
});

require(['lib/foo', 'app/bar', 'app/app'], function(foo, bar, app) {
  // use foo bar app do sth
});

baseUrl为:scripts目录

moduleID为:lib/foo, app/bar, app/app

根据baseUrl +
moduleID,以及自行补后缀.js,最终这三只module的js文件路径为:

scripts/lib/foo.js
scripts/app/bar.js
scripts/app/app.js

例2,项目结构以及例1:

main.js改为:

require.config({
  baseUrl: 'scripts/lib',
  paths: {
   app: '../app'
  }
});


require(['foo', 'app/bar', 'app/app'], function(foo, bar, app) {
  // use foo bar app do sth
});

此处出现了一个初的配备paths,它的来意是针对module
ID中一定的一部分,进行转义,如以上代码中针对app这个有,转义为../app,这代表一个相对路径,相对位置是baseUrl所指定的目录,由种布局会,../app其实对应的凡scirpt/app目录。正因有夫转义的在,所以上述代码中的app/bar才会被科学解析,否则还按baseUrl
+
moduleID的平整,app/bar不是应该让分析成scripts/lib/app/bar.js吗,但实际并非如此,app/bar被分析成scripts/app/bar.js,其中由关键作用的就是是paths的配备。通过这比喻,可以见到module
ID并不一定是js文件路径中之均等组成部分,paths的安排于路径过程的js特别实用,因为好简化其的module
ID。

另外第一个模块的ID为foo,同时没有paths的转义,所以依据分析规则,它的文本路径时:scripts/lib/foo.js。

paths的布局中只有当模块位于baseUrl所指定的文本夹的同层目录,或者更上层的目时,才会就此到../这种相对路径。

例3,项目结果以及例1,main.js同例2:

此间要验证的题目不怎么特殊,不盖main.js为例,而因app.js为条例,且app依赖bar,当然config还是要以main.js中定义的,由于斯问题在概念模块的时段更大,所以用define来举例,假设app.js模块如下概念:

define(['./bar'], function(bar) {
   return {
     doSth: function() {
       bar.doSth();
     }
   }
});

点的代码通过define定义了一个模块,这个define函数后面介绍如何定义模块的上重新来介绍,这里大概询问。这里这种用法的率先只参数跟require函数一样,是一个仗数组,第二独参数是一个回调,也是以享有因加载成功之后调用,这个回调的回到值会成为是模块的援被另外模块所利用。

此而说的题材或者和解析规则相关的,如果全恪守RJ的剖析规则,这里的仗应该安排成app/bar才是科学的,但由于app.js与bar.js位于与一个索引,所以全只是利用./这个和目录的对立标识符来解析js,这样的话只要app.js已经加载成功了,那么去和目录下找bar.js就得能够找到了。这种布局于概念模块的时候死有含义,这样您的模块就不依靠让放置这些模块的文书夹名称了。

4.06 RJ的异步加载
RJ不管是require方法还是define方法的仗模块都是异步加载的,所以下的代码不自然能分析及科学的JS文件:

<script data-main="scripts/main" src="scripts/require.js"></script>
<script src="scripts/other.js"></script>
//main.js
require.config({
  paths: {
    foo: 'libs/foo-1.1.3'
  }
});
//other.js
require( ['foo'], function( foo ) {
  //foo is undefined
});

由main.js是异步加载的,所以other.js会比其先加载,但是RJ的布在于main.js里面,所以于加载other.js读不顶RJ的部署,在other.js执行的上解析出的foo的路线就是会见化为scripts/foo.js,而正确路线应该是scripts/libs/foo-1.1.3.js。

尽管RJ的仗是异步加载的,但是已经加载的模块于数因之早晚,不会见重重复加载:

define(['require', 'app/bar', 'app/app'], function(require) {
  var bar= require("app/bar");
  var app= require("app/app");
  //use bar and app do sth
});

点的代码,在callback定义之时候,只所以了一个形参,这第一是以减小形参的多寡,避免一切回调的签字很丰富。依赖之模块于回调内部可以直接用require(moduleID)的参数得到,由于当回调执行前,依赖的模块已加载,所以这边调用不会见还又加载。但是倘若这里获取一个并无以负数组中冒出的module
ID,require很有或获得不至拖欠模块引用,因为它可能需要重新加载,如果她从不于其它模块中让加载了的言辞。

4.07 RJ官方推荐的JS文件组织结构 RJ建议,文件组织尽量扁平,不要多重合嵌套,最优良之是暨项目有关的位于一个文件夹,第三正库在一个文书夹,如下所示:

图片 3

4.08 使用define定义模块 AMD规定之模块定义规范为:

define(id?, dependencies?, factory);

其中:
id: 模块标识,可以省略。
dependencies: 所依赖的模块,可以省略。
factory: 模块的实现,或者一个JavaScript对象

关于率先只参数,本文不见面涉及,因为RJ建议所有模块都毫不以第一个参数,如果以第一单参数定义之模块成为命名模块,不适用第一独参数的模块成为匿名模块,命名模块如果重复称,所有因它的模块都得改!第二只参数是赖数组,跟require一样,如果没有是参数,那么定义的即使是一个凭依靠之模块;最后一个参数是回调或者是一个略对象,在模块加载了后调用,当然没有第二单参数,最后一个参数为会调用。

遵有的所举例都采用如下项目结构:

图片 4

  1. 概念简单对象模块:

app/bar.js

define({
 bar:'I am bar.'
});
利用main.js测试:
require.config({
  baseUrl: 'scripts/lib',
  paths: {
    app: '../app'
  }
});

require(['app/bar'], function(bar) {
  console.log(bar);// {bar: 'I am bar.'}
});
  1. 概念无据之模块:

app/nodec.js:

define(function () {
  return {
    nodec: "yes, I don't need dependence."
  }
});

利用main.js测试:

require.config({
  baseUrl: 'scripts/lib',
  paths: {
    app: '../app'
  }
});

require(['app/nodec'], function(nodec) {
  console.log(nodec);// {nodec: yes, I don't need dependence.'}
});
  1. 概念依赖其它模块的模块:

app/dec.js:

define(['jquery'], function($){
  //use $ do sth ...
  return {
    useJq: true
  }
});

利用main.js测试:

require.config({
  baseUrl: 'scripts/lib',
  paths: {
    app: '../app'
  }
});

require(['app/dec'], function(dec) {
  console.log(dec);//{useJq: true}
});
  1. 巡回依赖:
    当一个模块foo的倚重数组中留存bar,bar模块的借助数组中设有foo,就会形成巡回依赖,稍微修改下bar.js和foo.js如下。

app/bar.js:

define(['foo'],function(foo){
 return {
 name: 'bar',
 hi: function(){
  console.log('Hi! ' + foo.name);
 }
 }
});

lib/foo.js:

define(['app/bar'],function(bar){
 return {
 name: 'foo',
 hi: function(){
  console.log('Hi! ' + bar.name);
 }
 }
});

利用main.js测试:

require.config({
  baseUrl: 'scripts/lib',
  paths: {
    app: '../app'
  }
});


require(['app/bar', 'foo'], function(bar, foo) {
  bar.hi();
  foo.hi();
});

运行结果:

图片 5

一经转main.js中require部分底依顺序,结果:

图片 6

巡回依赖导致个别独依靠的module之间,始终会起一个以赢得其它一个底当儿,得到undefined。解决方法是,在概念module的时光,如果用到循环依赖之上,在define内部通过require重新赢得。main.js不变,bar.js改成为:

define(['require', 'foo'], function(require, foo) {
  return {
    name: 'bar',
    hi: function() {
     foo = require('foo');
      console.log('Hi! ' + foo.name);
    }
  }
});

foo.js改成:

define(['require', 'app/bar'], function(require, bar) {
  return {
    name: 'foo',
    hi: function() {
     bar = require('app/bar');
      console.log('Hi! ' + bar.name);
    }
  }
});

采取上述代码,重新履行,结果是:

图片 7

模块定义总结:不管模块是用回调函数定义还是略对象定义,这个模块输出的凡一个引用,所以这个引用得是可行的,你的回调不可知返回undefined,但是未囿于为对象类型,还可以是一再组,函数,甚至是主导项目,只不过要回去对象,你会由此是目标组织再度多之接口。

4.09 内置的RJ模块
还看看是代码:

define(['require', 'app/bar'], function(require) {
  return {
    name: 'foo',
    hi: function() {
      var bar = require('app/bar');
      console.log('Hi! ' + bar.name);
    }
  }
});

仗数组中的require这个moduleID对应之是一个搭模块,利用她加载模块,怎么用你曾经看到了,比如以main.js中,在define中。另外一个置于模块是module,这个模块跟RJ的另外一个布置有关,具体用法请在第5大部分失去了解。

4.10 其它RJ有用功能 1. 转变相对于模块的URL地址

define(["require"], function(require) {
  var cssUrl = require.toUrl("./style.css");
});

这意义于您想如果动态地加载一些文本的时节有因此,注意要下相对路径。

  1. 控制台调试

require(“module/name”).callSomeFunction() 而你想当控制台中查看有模块都发怎么样方法可调用,如果是模块已以页面加载的下经过依赖让加载了后,那么就可据此以上代码在控制台中做各种测试了。

5. RequireJS常用配置总结 以RJ的布置中,前面早已接触到了baseUrl,paths,另外几单常因此的配备是:

  • shim
  • config
  • enforceDefine
  • urlArgs

5.01 shim
为那些无动用define()来声称指关系、设置模块的”浏览器全局变量注入”型脚论开依赖以及导出配置。

例1:利用exports将模块的全局变量引用和RequireJS关联

main.js如下:

require.config({
  baseUrl: 'scripts/lib',
  paths: {
    app: '../app'
  },
  shim: {
   underscore: {
   exports: '_'
   }
  }
});

require(['underscore'], function(_) {
  // 现在可以通过_调用underscore的api了
});

万一您所显现,RJ在shim中补充加了一个针对性underscore这个模块的布置,并通过exports属性指定该模块暴露的全局变量,以便RJ能够对这些模块统一保管。

例2:利用deps配置js模块的仗

main.js如下:

require.config({
  baseUrl: 'scripts/lib',
  paths: {
    app: '../app'
  },
  shim: {
   backbone: {
    deps: ['underscore', 'jquery'],
    exports: 'Backbone'
   }
  }
});

require(['backbone'], function(Backbone) {
  //use Backbone's API
});

出于backbone这个组件依赖jquery和underscore,所以可以由此deps属性配置它的赖,这样backbone将会晤在另外两单模块加载了后才会加载。

例3:jquery等库插件配置方式

代码举例如下:

requirejs.config({
  shim: {
    'jquery.colorize': {
      deps: ['jquery'],
      exports: 'jQuery.fn.colorize'
    },
    'jquery.scroll': {
      deps: ['jquery'],
      exports: 'jQuery.fn.scroll'
    },
    'backbone.layoutmanager': {
      deps: ['backbone']
      exports: 'Backbone.LayoutManager'
    }
  }
});

5.02 config
常常用将布信息污染给一个模块。这些配置往往是application级别之音,需要一个一手将其于下传递让模块。在RequireJS中,基于requirejs.config()的config配置起来落实。要博这些消息之模块可加载特殊之依赖“module”,并调用module.config()。

例1:在requirejs.config()中定义config,以供应其他模块使用

requirejs.config({
  config: {
    'bar': {
      size: 'large'
    },
    'baz': {
      color: 'blue'
    }
  }
});

要你所呈现,config属性中之bar这等同节省是在用于module
ID为bar这个模块的,baz这无异于节是用于module
ID为baz这个模块的。具体用以bar.js举例:

define(['module'], function(module) {
  //Will be the value 'large'var size = module.config().size;
});

前面提到了,RJ的放置模块除了require还有一个module,用法虽以此,通过它们可来加载config的内容。

5.03 enforceDefine 设若安也true,则当一个剧本不是透过define()定义且非负有可供应检查的shim导出字串值时,就会见废弃来错误。这个特性可以强制要求具有RJ依赖或加载的模块都设由此define或者shim被RJ来管理,同时其还有一个益处虽用来错误检测。

5.04 urlArgs
RequireJS获取资源时增大在URL后面的附加的query参数。作为浏览器还是服务器不对配置时之“cache
bust”手段特别有因此。使用cache bust配置的一个演示:

urlArgs: “bust=” + (new Date()).getTime()
6. 错误处理
**
6.01 加载错误的抓获
**IE中抓获加载错误不完善:

IE
6-8被之script.onerror无效。没有办法判断是否加载一个脚本会导致404摩擦;更充分地,在404中依旧会触发state为complete的onreadystatechange事件。
IE
9+中script.onerror有效,但发生一个bug:在尽脚本后其并无触发script.onload事件句柄。因此它无法支撑匿名AMD模块的科班方法。所以script.onreadystatechange事件仍让下。但是,state为complete的onreadystatechange事件会以script.onerror函数触发之前接触。
就此为了支持以IE中抓获加载错误,需要配置enforceDefine为true,这只能要求您有着的模块都为此define定义,或者用shim配置RJ对其的援。

留神:如果你设置了enforceDefine:
true,而且若采取data-main=””来加载你的主JS模块,则该主JS模块必须调用define()而休是require()来加以载其所用的代码。主JS模块仍然只是调用require/requirejs来安装config值,但对模块加载必须动define()。比如原本的当下段就是会见报错:

require.config({
 enforceDefine: true,
  baseUrl: 'scripts/lib',
  paths: {
    app: '../app'
  },
  shim: {
   backbone: {
   deps: ['underscore', 'jquery'],
      exports: 'Backbone'
   }
  }
});
require(['backbone'], function(Backbone) {
  console.log(Backbone);
});

把最后三实行改化:

define(['backbone'], function(Backbone) {
  console.log(Backbone);
});

才无会见报错。

6.02 paths备错

requirejs.config({
  //To get timely, correct error triggers in IE, force a define/shim exports check.
  enforceDefine: true,
  paths: {
    jquery: [
      'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min',
      //If the CDN location fails, load from this location
      'lib/jquery'
    ]
  }
});

//Later
require(['jquery'], function ($) {
});

上述代码先品尝加载CDN版本,如果差,则退到地头的lib/jquery.js。

小心:
paths备错仅在模块ID精确匹配时工作。这不一于正规的paths配置,常规配置可匹配模块ID的人身自由前缀有。备错主要用以深的左恢复,而未是常规的path查找分析,因为那在浏览器被是废的。

6.03 全局 requirejs.onError 为抓获在局域的errback中无捕获的雅,你可重载requirejs.onError():

requirejs.onError = function (err) {
  console.log(err.requireType);
  if (err.requireType === 'timeout') {
    console.log('modules: ' + err.requireModules);
  }

  throw err;
};

以上就是本文的全部内容,希望对大家之读抱有助。

不过开头代码量小也远非经历,直接以html引用所有js文件。后来抓得html文件越来越好,js的顺序一乱七八糟,就报奇奇怪怪的荒谬,找半上。

君可能感兴趣之章:

  • LABjs、RequireJS、SeaJS的区别
  • SeaJS 与 RequireJS 的差别对比
  • JavaScript的RequireJS库入门指南
  • 优化RequireJS项目的连锁技能总结
  • 应用RequireJS优化JavaScript引用代码的道
  • 在JavaScript应用中行使RequireJS来兑现延迟加载
  • RequireJS入门平等底实现率先只例
  • 小心!AngularJS结合RequireJS做文件合并减的那些坑

http://www.bkjia.com/Javascript/1096181.htmlwww.bkjia.comtruehttp://www.bkjia.com/Javascript/1096181.htmlTechArticle一篇文章掌握RequireJS常用知识,一篇掌握requirejs
本文用渐进的法子,从理论及实践,从RequireJS官方API文档中,总结出在用RequireJ…

第二独品种,我就算想方如更上一层楼,直奔声名显赫的RequireJS去了。但RequireJS真的酷麻烦来木有!平添了好多代码,和AngularJS的Dependency
Injection长得还特别像,一不小心就整混。时不时报个Script
Error出来,根本无知晓问题在何。

来没有起重复简明的办法吧?正想在为,ng-newsletter如出一辙望炮响,送来了当时首稿子。作者Jeff
Dickey介绍了于是模块来集团代码的季种植方法,依照推荐程度,依次为:

  • Require.js (Implementation of AMD)
  • Browserify (Implementation of CommonJS)
  • Angular dependency injection
  • ES6 modules

笔者着重写了以第三种基础及,组织代码的简化方法(捂脸,我才故到第一种植)。

模块的功效,首先是一旦切断命名空间。Angular的模块机制很好地解决了。除了angular这个目标自我,没有其它暴露于Global里的靶子。

接下来是拍卖依赖关系。Angular的模块同样指定了负关系,而Dependency
Injection在更细致之粒度上做了近乎的从。

双重全的凡,Angular模块的概念顺序可以任由。各个service、controller、directive注册到模块的次第,也无限定。唯一的求就是:模块要先期定义,后使。请看下的例子:

// 模块可以按任意的顺序定义
angular.module('app', ['ctrl']);
angular.module('ctrl', ['svc']);
angular.module('svc', []);

// 使用尚未注册的GithubSvc
angular.module('ctrl')
.controller('GithubCtrl', function ($scope, GithubSvc) {
  GithubSvc.fetchStories().success(function (users) {
    $scope.users = users;
  });
});

angular.module('svc')
.factory('GithubSvc', function ($http) {
  return {
    fetchStories: function () {
      return $http.get('https://api.github.com/users');
    }
  };
});

可是运行的代码在是jsFiddle。

Angular没有拉咱缓解之,就剩下文件加载了。既然加载顺序无关紧要,那直拿公文合并起来不就是哼了?反正最终都要统一之。

gulp.task('js', function () {
  gulp.src(['src/**/module.js', 'src/**/*.js'])
    .pipe(concat('app.js'))
    .pipe(gulp.dest('.'))
})

不管以工作要按照功能分目录,只要将每个模块的概念都居目录下之module.js里,保证拥有模块于用之前还早已定义了了,直接concat毫无问题。html里倒只是发生一行:

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

编制、测试或以模块分目录及文书,代码组织清晰利落。拼接到一起在浏览器上走。发布时,再ngAnnotateuglify霎时间尽管好。

库房底代码,再拼出一个vender.js就行了。gulp-bower-files以此插件,可以分析bower.json,把依的每个库里的main属性组合起来,创建gulp.src()

gulp.task('vendor', function () {
  gulpBowerFiles()
    .pipe(concat('vendor.js'))
    .pipe(gulp.dest('.'))
})

历次手工gulp js不方便?gulp watch起来。

gulp.task('watch', ['js'], function () {
  gulp.watch('src/**/*.js', ['js'])
})

当然,这些还是权宜之计,因为传说着之ES6和Angular
2.0,将搞定这些问题。不过在此之前,不妨试试这超简单的艺术了。


[补充]

  1. gulp-bower-files已被main-bower-files取代。
  2. moduleconfig路是出各个依赖之。比如,要定义route里的controller,就要求该controller须有。

相关文章