requirejs使用入门

什么是requirejs?

  RequireJS的目标是鼓励代码的模块化,它使用了不同于传统<script>标签的脚本加载步骤。可以用它来加速、优化代码,但其主要目的还是为了代码的模块化。它鼓励在使用脚本时以module ID替代URL地址。

RequireJS以一个相对于baseUrl的地址来加载所有的代码。 页面顶层<script>标签含有一个特殊的属性data-main,require.js使用它来启动脚本加载过程,而baseUrl一般设置到与该属性相一致的目录。

为什么要使用require.js?

  我们在做项目的过程中,往往都需要加载很多个js文件,如下所示:

  1.   <script src="1.js"></script>
  2.   <script src="2.js"></script>
  3.   <script src="3.js"></script>
  4.   <script src="4.js"></script>
  5.   <script src="5.js"></script>
  6.   <script src="6.js"></script>

  这样的写法的缺点是Js会阻塞渲染页面,并且文件越多, 那么等待的时间也就越长,并且文件多的情况下往往还存在文件间依赖的问题, 有时候比较复杂,那么文件间的依赖就成了问题。

  所以require.js主要就是为了解决下面的两个问题:

(1)实现js文件的异步加载,避免页面失去响应。

(2)管理项目之间的依赖性,便于代码的维护和管理。

如何使用require.js?

  require.js下载地址

  使用require.js非常简单,只需要在页面中使用一个require.js即可,如下所示:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>require</title>
  6. <script src="./require.js" data-main="js/main" type="text/javascript"></script>
  7. </head>
  8. <body>
  9. <!-- your code is here -->
  10. </body>
  11. </html>

  即我们在html文件中只需要使用一个require.js文件的引入即可,然后data-main引入的是网页程序的主模块,这个文件会被require.js第一个加载,由于require.js默认文件的后缀名为.js,所以这里我们写成main即可。

  

如何写主模块main.js

  什么是主模块?

    主模块就是入口文件,它是require.js加载执行的第一个文件,这就是主模块,并且其他的所有js文件将在这里被引入执行。

  为什么要使用主模块?

    我们知道require.js在index.html唯一的被引入,而没有引入其他js文件,这也是为了方便管理。 那么内部机制就要求需要这么一个主模块,然后就可以很好的管理模块之间的关系,试想如果没有这么一个主模块,那么require.js也会无从下手的。

  main.js中怎么写呢? 如果我们只需要这一个js就够了,比如就执行alert("hello");那么main.js文件中只有这么一句:

  1. alert("hello");

  然后打开html文件时,就会alert("hello");了,但是我们使用require.js不可能就使用这么一个文件,否则就不用require了。

  真正的情况是: 主文件main.js依赖于其他文件, 这时就要使用AMD规范来定义require()函数。如下所示:

  1.  // main.js
  2.   require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
  3.     // some code here
  4.   });

  即接受的第一个参数是一个数组,指定模块名称(不带.js的文件), 然后第二个参数是一个函数,其中的参数暴露出了模块中暴露的方法,然后我们就可以在回调函数中使用这些模块了。

  require()异步加载moduleA,moduleB和moduleC,浏览器不会失去响应;它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。

  

  例子

  比如之前的index.html中的body部分是<div class="wrap"></div>,然后引入了require.js并指定了main.js为入口文件,在main.js中定义如下:

  1. require(['jquery'],function ($) {
  2. $('.wrap').html("hello, world!");
  3. });

  即我们只引入了jquery,并且在回调函数中将$暴露出来并使用,那么启动index.html文件之后,我们就可以在页面上看到渲染的hello, world了。 注意: 此时的目录结构如下:

  所以:我们需要注意下面的几点:

  • require.js会默认认为require()中第一个参数数组里的文件和main.js在同一个目录下
  • 我们引入的文件即jquery.js,因为默认是.js后缀,所以我们直接写文件名即可。
  • 在require的回调函数中,我们使用回调函数中的接口,即如果这里没有定义为$,而是定义为foo,那么我们就需要使用foo。

  、

存在的问题如果说依赖文件(如jquery)何main.js文件不再同一个目录中该怎么引用呢

  比如现在的目录时这样的:

  那么现在我们就会发现,你在require函数的第一个参数中写成'jquery'或者‘lib/jquery’或者‘../lib/jquery’或者‘./lib/jquery’都是无法成功的

  这时我们就需要使用require.config()方法对路径进行配置了。如下所示:

  1. require.config({
  2. paths: {
  3. jquery: '/lib/jquery'
  4. }
  5. });

  如果有多个文件,并且多个文件在同样的目录下,我们可以定义一个baseUrl, 如下:

  1.   require.config({
  2.     baseUrl: "js/lib",
  3.     paths: {
  4.       "jquery": "jquery.min",
  5.       "underscore": "underscore.min",
  6.       "backbone": "backbone.min"
  7.     }
  8.   });

  如果某个模块在另一个主机上,我们可以直接定义其网址:

  1.  require.config({
  2.     paths: {
  3.       "jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
  4.     }
  5.   });

如何定义模块?

  在使用require时,我们用的是AMD的规范进行加载的,所以在定义模块时,也是需要使用AMD规范来定义模块。

  比如现在我们在和main.js同一个目录下定义一个alert模块:

  1. define(function () {
  2. var alertName = function (str) {
  3. alert("I am " + str);
  4. }
  5. var alertAge = function (num) {
  6. alert("I am " + num + " years old");
  7. }
  8. return {
  9. alertName: alertName,
  10. alertAge: alertAge
  11. };
  12. });

  即使用define定义,其中接受一个回调函数作为参数,在这个回调函数中定义模块,最后返回一个对象,对象的属性就是我们可以调用的方法。

  然后我们看看如何在main.js中使用:

  1. require(['alert'], function (alert) {
  2. alert.alertName('JohnZhu');
  3. alert.alertAge();
  4. });

  即使用也非常简单,就是引入alert模块,然后调用其中的alertName和alertName方法即可。

  问题:如果一个模块在定义时需要依赖其他模块怎么办?

  比如这个alert模块需要依赖jquery,那么我们就可以这么定义:

  1. define(['jquery'],function () {
  2. var alertName = function (str) {
  3. alert("I am " + str);
  4. $('.wrap').html("I am " + str);
  5. }
  6. var alertAge = function (num) {
  7. alert("I am " + num + " years old");
  8. }
  9. return {
  10. alertName: alertName,
  11. alertAge: alertAge
  12. };
  13. });

  即我们直接将define的第一个参数(一个数组)中使用jquery, 然后直接使用即可。

  • 注意: 这里显然使用jquery的使用默认路径还是和main.js在同一个目录下。
  • 这里我们没有在回调函数中传入参数,但是是可以传的,只是省略了,如果我传入foo,那么就可以用foo(".wrap").html("I am " + str);来使用。
  • 于是main.js在加载alert模块时,会等到jquery模块加载完再执行其中的回调函数。

加载非规范的模块

  理论上,require.js加载的模块,必须是按照AMD规范、用define()函数定义的模块。但是实际上,虽然已经有一部分流行的函数库(比如jQuery)符合AMD规范,更多的库并不符合。那么,require.js是否能够加载非规范的模块呢?

  答案是可以的,但是需要在使用require之前,用require.config()方法定义一些他们的特征。

  1.   require.config({
  2.     shim: {
  3.  
  4.       'underscore':{
  5.         exports: '_'
  6.       },
  7.       'backbone': {
  8.         deps: ['underscore', 'jquery'],
  9.         exports: 'Backbone'
  10.       }
  11.     }
  12.   });

  之前我们介绍过require.config中的paths,这里又介绍了shim对象,它专门用来配置不兼容的模块。具体来说,每个模块要定义:

  (1)exports值(输出的变量名),表明这个模块外部调用时的名称;

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

   比如,我们可以这样定义一个jquery插件:

  1.   shim: {
  2.     'jquery.scroll': {
  3.       deps: ['jquery'],
  4.       exports: 'jQuery.fn.scroll'
  5.     }
  6.   }

  即deps说明他是需要依赖jquery的, exports说明可以通过juqery的scroll访问到它。

  

require.js插件

  requirejs还提供了一系列的插件供我们使用。

  domready插件,可以让回调函数在页面DOM结构加载完成后再运行。

  1.  require(['domready!'], function (doc){
  2.     // called once the DOM is ready
  3.   });

  text和image插件,则是允许require.js加载文本和图片文件。

  1.   define([
  2.     'text!review.txt',
  3.     'image!cat.jpg'
  4.     ],
  5.  
  6.     function(review,cat){
  7.       console.log(review);
  8.       document.body.appendChild(cat);
  9.     }
  10.   );

  

补充例子

  最近看到有人类似于这样使用require。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>require</title>
  6. <script src="./require.js" type="text/javascript"></script>
  7. </head>
  8. <body>
  9. <!-- your code is here -->
  10. <div class="wrap">
  11.  
  12. </div>
  13. <script>
  14. require(['js/dosomething']);
  15. </script>
  16. <script src="js/jquery.js"></script>
  17. </body>
  18. </html>

  dosomething是这样的:

  1. alert('god');
  • 即我们使用require来引入模块,但是dosomething这个模块并没有按照AMD规范来编写。
  • 我们可以看到利用require的好处在于可以异步加载文件。 这种用法的好处就是在于require的文件会异步加载。
  • 并且在我们引入的目的仅仅是执行一些功能,而不需要暴露出方法来,所以可以直接写

  

参考文档:

http://www.requirejs.cn/

http://www.ruanyifeng.com/blog/2012/11/require_js.html

使用require.js的更多相关文章

  1. Javascript模块化编程(三):require.js的用法

    Javascript模块化编程(三):require.js的用法 原文地址:http://www.ruanyifeng.com/blog/2012/11/require_js.html 作者: 阮一峰 ...

  2. javascript模块化编程(三):require.js用法

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

  3. require.js工作原理(初始)

    详情:请见阮一峰老师的日志:http://www.ruanyifeng.com/blog/2012/11/require_js.html: 导入:<script data-main=" ...

  4. Javascript模块化编程(三):require.js的用法(转)

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

  5. require.js源码分析

    写的寥寥草草,博客园的布局怎么弄还没有研究,再保存一份草稿,日后在完善,深度研究 require.js 加载顺序 1:加载html主页,require.js文件 2:脚本执行到html中的script ...

  6. Angular.JS + Require.JS + angular-async-loader 来实现异步加载 angular 模块

    传统的 angular 应用不支持异步加载模块,必须在 module 启动的时候,所有模块必须预加载进来. 通过使用 angular-async-loader 库,我们可以使用 requirejs 等 ...

  7. require.js

    日期: 2012年11月 7日 http://www.ruanyifeng.com/blog/2012/11/require_js.html 这个系列的第一部分和第二部分,介绍了Javascript模 ...

  8. require.js 入门笔记

    网站越来越庞大,JS也是越写越多. 当所有的JS 都集中在 HTML的 head 部分时,网页加载变得很慢,很多的 JS代码也并不是全都适用在当前的页面,造成了代码的冗余度非常高. 而且长长的JS代码 ...

  9. require.js 的使用

    一.为什么要用require.js 在同一个页面要加载多个js文件时,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长: 其次,由于js文件之间存在依赖关系,因此必须严格保证加载顺序(比 ...

  10. require.js笔记

    笔记参考来源:阮一峰  http://www.ruanyifeng.com/blog/2012/10/javascript_module.html   1. 浏览器端的模块只能采用“异步加载”方式 = ...

随机推荐

  1. 《Maven实战》笔记-3-Maven仓库

    一.Maven仓库的分类 1.本地仓库 一般来说,在Maven项目目录下,没有诸如lib/这样用来存放依赖文件的目录. 要自定义本地仓库目录地址时,可以编辑文件~/.m2/setting.xml,设置 ...

  2. Struts2 引入

    引入:   说:如果一个路径想访问一个类,需求怎么做? 第一种方法,用servlet 第二种方法,用过滤器 第三种方法如下图:把路径和方法都存到map里面,用反射可以执行类下的方法     第三中方法 ...

  3. angular 分页2

    http://www.alliedjeep.com/2547.htm AngularJS Code (Users.js) var Users = angular.module('Users', []) ...

  4. java eclipse导出可运行jar包(java服务)和导入

    java   eclipse导出可运行jar包(java服务)和导入 二.导出可运行包步骤: 1.选择要导出的项目:  2.右键项目-单击export:  3.选择导出类型:(Runnable JAR ...

  5. 读《JavaScript权威指南》笔记(三)--对象

    1.对象介绍 对象是JavaScript的基本数据类型.对象是一种复合值:它将很多值(原始值或者其他对象)聚合在一起,可通过名字访问这些值.对象也可看做是属性的无序集合,每个属性都是一个名/值对.属性 ...

  6. Java基础之8个基本类型及基本类型间转换

    8种基本数据类型 Java语言有8种基本数据类型, 分别用于存储整数.浮点数.字符数据和布尔类型数据.需要注意的是: 现在所介绍的仅仅是基本数据类型,后续还会介绍很多非基本数据类型.基本数据类型如图 ...

  7. Hyperledger Fabric java chaincode 编译部署(1.4V)

    前提条件: 构建好了一个拥有四个peer 一个Order 的1.4版本的Fabric网络. 证书通过Cryptogen生成,没有使用CA服务. 开启TLS. 网络中的peer都加入了一个 名为mych ...

  8. java方法里面生成js弹出框

    核心代码:方法参数要有response response.setContextType("text/html;charset=UTF-8"); PrintWrite out = r ...

  9. DP【洛谷P4290】 [HAOI2008]玩具取名

    P4290 [HAOI2008]玩具取名 某人有一套玩具,并想法给玩具命名.首先他选择WING四个字母中的任意一个字母作为玩具的基本名字.然后他会根据自己的喜好,将名字中任意一个字母用"WI ...

  10. 模板【洛谷P3390】 【模板】矩阵快速幂

    P3390 [模板]矩阵快速幂 题目描述 给定n*n的矩阵A,求A^k 矩阵A的大小为n×m,B的大小为n×k,设C=A×B 则\(C_{i,j}=\sum\limits_{k=1}^{n}A_{i, ...