RequireJS 快速入门
说明:本文只提供快速入门内容,方便快速进入实战状态。更高级的配置,请参考官网文档。
当初之所以使用 RequireJS 等工具,是因为想提高js的加载速度,避免不必要的堵塞。但通过一段时间的使用,发现 RequireJS 更重要的作用是作为命名空间使用。
一、基本用法
RequireJS 官网文章不是中文的,篇幅不少(官方网址:http://requirejs.org)。网上的其他相关文章,有的讲的也很复杂。
其实,RequireJS 极其简单。如果你对 c# 或 java 语言的命名空间有一点点了解,那么,RequireJS 的用法和作用,可以用 c# 中的两行代码来类比说明:
using xx=wojilu.Core;
namespace MyApp {
public class MyClass {
public void MyTest() {}
}
}
RequireJS主要的功能,就是实现c#代码的第一行和第二行的功能:1)引入需要使用的命名空间(顺便加个别名也行);2)将自己的代码放到命名空间中,避免全局污染。
因为 javascript 天生的缺点,语言本身没有集成命名空间的概念,所以变量名、函数名很容易发生冲突。这些年,大家想尽了各种办法,给 js 添加命名空间的概念,其中最成熟的套路,就是 RequireJS 这种。
我们可以看到,在c#中只要两行代码的事情,在 js 中,得用多么复杂的类库,比如 RequireJS 去解决。
下面我们看一下 RequireJS 的具体写法,新建一个独立的 wojilu.test1.js 文件,然后输入如下代码:
define( ['wojilu.Core'], function(xx) {
return {
MyTest : function() { alert( 'wojilu1 module' );}
};
});
和上面的c#代码对比一下,RequireJS 同样也做了两件事情:
1、引入命名空间 wojilu.Core,同时给它取了一个别名 xx;
2、将自己的所有代码放在 define 中,避免全局化的污染冲突。
总之,RequireJS 定义了(define)一个命名空间,在定义的时候,顺便引用了需要使用其他命名空间。我们注意到,按照 RequireJS 的术语,它把命名空间叫做“模块”。注意,在这里,RequireJS 定义的模块(命名空间)是匿名的,没有取名,这是和c#不同的地方。
但这个不要紧,因为其他 js 在用到你这个 js 的时候,一般是根据文件名称加载的,同时可以通过上面的 xx 这种方式,给模块(命名空间)自定义别名,所以,取不取名,还真不是关键。
我们新建另外一个 wojilu.test2.js 文件,来使用 wojilu.test1.js:
define( ['wojilu.test1'], function( t1 ) {
return {
NewTest : function() { t1.MyTest();}
};
});
同样,也是通过文件名(不需要后缀名),引入了 wojilu.test1 命名空间,并给它取了别名 t1,然后在代码中使用 t1.MyTest() 方法。
按照 RequireJS 的规范,所有的模块定义,都必须放在 return {} 对象中。也就是说,你的代码都要写在 return 返回的 {} 对象里面。这会不会导致代码臃肿难看?当然不会。你可以重构一下,比如这样做:
define( ['wojilu.test1'], function( t1 ) { function someFunc1() {
// 实际主要代码
} function someFunc2() {
// 实际主要代码
}
// 通过 return 方式,将需要公开的函数暴露出来,供其他 js 调用
return {
NewTest : function() { t1.MyTest();},
fun1 : someFunc1,
fun2 : someFunc2
};
});
当然,要使用 RequireJS 的这些功能,你必须在页面中引用 require.js 文件
<script src="require.js"></script>
二、其他用法
上面的用法是标准用法,但 RequireJS 在加载其他 “模块/命名空间/js文件” 的时候,内部是通过传统的 <script src="some.js"></script> 来实现的,所以,你也可以把 RequireJS 仅仅当做 js 加载器使用。比如这行代码:
<script src="some.js"></script>
可以写成:
<script>require( ["some" ] );</script>
虽然仅仅是写法的变化,但带来了很多好处:
1、避免阻塞,提高了 js 的加载性能;
2、通过编程使用 require 方法加载,而不是<script>硬写,更加灵活。
三、基本配置
上面使用 RequireJS 的方式是这样处理的:
<script src="require.js"></script>
这种写法虽然简单,但其实并不推荐,一般的写法还要再加个属性:
<script data-main="js/main" src="js/require-jquery.js"></script>
就像一个c程序总有一个 main 方法作为入口一样,上面这种写法,做了几件事情:
1、加载了 require-jquery.js 文件。注意,官方提供了 RequireJS 和 jquery 的打包版本,推荐。
2、在加载之后,加载入口文件 js/main.js ,注意,main.js 写进去的时候,不需要后缀名。
你的所有其他 js 模块文件,都可以写在 main.js 里面,通过 main.js 加载。
四、加载的用法
到此为止,我们遇到了两个关键词,一个是 define ,可以用来定义模块(命名空间),第一部分我们讲了;还有一个是 require,可以直接加载其他 js。它除了简单的用法:
<script>
require( ["some" ] );
</script>
之外,还有和 define 类似的复杂用法:
<script>
require(["aModule", "bModule"], function() {
myFunctionA(); // 使用 aModule.js 中的函数 myFunctionA
myFunctionB(); // 使用 bModule.js 中的函数 myFunctionB
});
</script>
总结一下,define 是你定义自己的模块的时候使用,可以顺便加载其他js;require 直截了当,供你加载用的,它就是一个加载方法,加载的时候,可以定义别名。
五、在 RequireJS 之前运行
有了 RequireJS 这个工具,我们可以将网页 <head> 中的所有 js 都挪到页脚,以提高 js 的加载速度。请在 www.wojilu.com 网页上右键查看 html 源码,看一下实际效果。
理论上,js 脚本都应该放到独立的 js 文件中,而不是直接嵌入网页内联执行,好处是方便浏览器缓存,不用每次都加载页面内容。但只要你不是有真正的代码洁癖,总有一些特殊时候,需要在加载 require.js 之前,运行一些script脚本。这时候,你可以使用 wojilu 目前的做法,把所有的代码都放在一个叫 _run 的函数中,比如在 require.js 加载代码上面一行:
<script>
_run(function () {
require(['wojilu.core.base'], function (x) { x.customSkin().backTop(); });
});
</script>
这行代码引用了 wojilu.core.base 文件,但因为是放在 _run 中的,所以并不是立刻执行,而是延迟到 require.js 加载之后执行。 run 表示运行,前面加上下划线,表示“延迟”运行。
至于wojilu如何做到这一点的,请自己阅读源码,其实思路是很简单的。
六、版本号
为了在js更新之后,及时通知客户端刷新缓存,我们一般需要给js加上版本号,具体说明,参看这里:http://www.wojilu.com/Common/Page/13 。在 RequireJS 中也可以给所有需要加载的 js 加上版本号,方法是给 require.js 提供一个配置文件。请在 requrie.js 加载之前,提供一个全局变量 require:
<script>
var require = {
urlArgs: 'v=版本号'
};
</script>
<script src="scripts/require.js"></script>
注意:不要把 require 变量写成 window.require ,据说在IE下会有问题。
RequireJS 还提供了其他丰富的配置选项,具体请访问官网查看。
七、其他问题
1、路径与后缀名
在 require 一个 js 文件的时候,一般不需要加上后缀名。如果加上后缀名,会按照绝对路径加载。没有后缀名,是按照下面的路径加载:
<script data-main="js/main" src="js/require-jquery.js"></script>
也就是默认加载 data-main 指定的目录,即 js/main.js 文件所在的目录。当然,你可以通过配置文件修改。
2、define 定义模块方法只能用在独立的js文件中,不能在页面中直接使用。
否则会报 Mismatched anonymous define() module 错误。
3、和其他第三方js类库是否冲突?
不会冲突。一般比较规范的类库,都会给自己的js加上命名空间。比如 wojilu 旧有的 wojilu.common.js ,其实就是放在 wojilu 命名空间中(当然是通过更原始的方式实现命名空间的)。
在通过 RequireJS 加载这些第三方的 js 的时候,完全不要有任何担忧。
当然,如果第三方类库能够使用 RequireJS 的方式进行改造,那是最好。比如 wojilu 中大多数js 都按照 RequireJS 的方式进行了改造。但是,如果你不改造,也是完全不要紧的。
4、在代码中 require 一个文件多次,是否会导致浏览器反复加载?
不会,这是 RequrieJS 的优点,即使你反复 require 它,它只加载一次。
RequireJS 快速入门的更多相关文章
- angularAMD快速入门
ngularAMD是作者 marcoslin 使用 RequireJS + AngularJS开发的前端mvvm框架,因此你可以使用它快速创建一款Web App.他特别适合快速开发SPA应用,适当的和 ...
- Web Api 入门实战 (快速入门+工具使用+不依赖IIS)
平台之大势何人能挡? 带着你的Net飞奔吧!:http://www.cnblogs.com/dunitian/p/4822808.html 屁话我也就不多说了,什么简介的也省了,直接简单概括+demo ...
- SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)
SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=>提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/si ...
- 前端开发小白必学技能—非关系数据库又像关系数据库的MongoDB快速入门命令(2)
今天给大家道个歉,没有及时更新MongoDB快速入门的下篇,最近有点小忙,在此向博友们致歉.下面我将简单地说一下mongdb的一些基本命令以及我们日常开发过程中的一些问题.mongodb可以为我们提供 ...
- 【第三篇】ASP.NET MVC快速入门之安全策略(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- Mybatis框架 的快速入门
MyBatis 简介 什么是 MyBatis? MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果 ...
- grunt快速入门
快速入门 Grunt和 Grunt 插件是通过 npm 安装并管理的,npm是 Node.js 的包管理器. Grunt 0.4.x 必须配合Node.js >= 0.8.0版本使用.:奇数版本 ...
- 【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
随机推荐
- 对点餐APP现阶段开发的问题
团队的成立,基本是一气呵成.但是,github团队的建立却成为 第一个难题,大家对github都不熟,又刚刚好没课时间的任务,大家 已经各有安排,造成时间上的紧急.没有按时.按要求完成github的 ...
- python css基本操作
1. 概述 css是英文Cascading Style Sheets的缩写,称为层叠样式表,用于对页面进行美化. 存在方式有三种:元素内联.页面嵌入和外部引入,比较三种方式的优缺点. 语法:style ...
- position
1.父集设置了relative,子集的absolute要设置top和left的值,不然父集的padding值会影响到子集的位置: #first{ width: 200px; height: 100px ...
- WEB启动时就加载servlet的dopost方法
web启动的时候可以加载servlet的init方法,无法加载dopost方法,如果你需要什么内容在启动的时候执行,可以将内容放到init方法里面,dopost方法,是在客户端使用post请求的时候才 ...
- Android仿“守望先锋”加载动画
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 效果图 实现思路 画一个小六边形 按效果图位置画七个小六边形 实现一个小六边形的显示与隐藏 ...
- [osx] android studio下修改avd的hosts文件
1. 启动avd 安装/启动avd就不说啦,可以直接在android studio里面操作的 2. 进入adb目录 当然是打开终端来敲命令啦. cd /Users/birdylee/Library/A ...
- 修改后的CopyFile类
这是修改后的CopyFile类,前面那个类有局限性,它不能复制大文件 这是我第一次写成一个能够实际应用的类,感谢博主们的无私奉献,感谢SeayXu老师的提点 但是这个类也并不是完美无缺,它复制文件没有 ...
- 关于oracle中in和exists的区别
一般来说,这两个是用来做两张(或更多)表联合查询用的,in是把外表和内表作hash 连接,而exists 是对外表作loop 循环,假设有A.B两个表,使用时是这样的: 1.select * from ...
- listview和checkbox的冲突的用法
package com.exaple.music; import java.util.List; import java.util.Timer; import java.util.TimerTask; ...
- Android Bootloader LittleKernel的两篇文章 【转】
转自:http://blog.csdn.net/loongembedded/article/details/41747523 2014-12-05 14:37 3599人阅读 评论(2) 收藏 举报 ...