在JavaScript应用中使用RequireJS来实现延迟加载

无论简单还是复杂的Web应用,都由一些HTML、JavaScript、CSS文件组成。通常开发者会通过JQuery、Knockout、Underscore等等这样的第三方JavaScript框架来提高开发速度。由于这些JavaScript框架都针对特定的用途开发而且已经得到了“验证”,所以直接使用它们就比自己从头实现所需要的功能显得更为合适。然而,伴随着应用的复杂度不断上升,写出干净、低耦合、可维护的代码变得越来越重要。在这篇文章里,我将解释 RequireJS框架如何帮助应用开发者写出更加模块化的代码,以及它是如何通过延迟加载JavaScript文件来提高应用性能的。

开始的部分我们先不用RequireJS框架,然后在下一个章节用RequireJS来重构它。

下面的这个HTML页面包含了一个id为“message”的<p>元素。当用户访问这个页面的时候,它将展示订单Id和客户姓名信息。

Common.JS文件包含了两个模块的定义——Order和Customer。函数showData和页面的body结合在一起,它通过调用write函数来把要输出的信息放入页面中。作为示例,我在showData函数里硬编码了Id为1,客户姓名为Prasad。

<!DOCTYPE html>
<html>
<head>
<title>JavaScript NonRequireJS</title>
<script src="common.js" type="text/javascript"></script>
</head>
<body>
<strong>Display data without RequireJS</strong>
<p id="message" />
<script type="text/javascript">
showData();
</script>
</body>
</html>
Common.JS

function write(message) {
  document.getElementById('message').innerHTML += message + '</br>';
}

function showData() {
  var o = new Order(1, "Prasad");
  write("Order Id : " + o.id + " Customer Name : " + o.customer.name);
}

function Customer(name) {
  this.name = name;
  return this;
}

function Order(id, customerName) {
  this.id = id;
  this.customer = new Customer(customerName);
  return this;
}

在浏览器中打开这个页面,你将看到如下的信息。

虽然上面的代码能够显示输出,但是它仍有一些问题:

  • Common.JS文件包含了所有需要定义的函数(write,showData),而且模块(Order,Customer)很难维护和复用。假如你想在其它页面里复用write函数并引用了上面的JavaScript文件,那么你也导入了这个页面可能不需要的其它函数和模块。
  • Order模块(或者在面向对象中叫做“类”)在初始化过程中创建了一个Customer模块的实例。这意味着Order模块依赖于Customer模块。这些模块间的紧耦合使得将来在优化时很难重构与维护。
  • 每当客户端请求这个页面时,Common.JS文件就会被载入DOM。在上面这个例子中,尽管我们只需要在页面上输出信息,但我们仍把那些不需要的模块(Customer,Order)载入了内存。载入不必要的应用资源(JavaScript、CSS、图片文件等等)会降低应用的性能。
  • Common.JS文件里的模块可以被分离到不同的JavaScript文件里,但是当应用变得越来越复杂时,很难判断JavaScript文件之间的依赖关系与需要被加载的文件的加载顺序。

RequireJS框架处理了JavaScript文件间的依赖关系,并且根据需要按顺序加载它们。

用RequireJS搭建应用

现在让我们看看重构过的代码。下面的HTML代码引用了Require.JS文件。data-main属性定义了这个页面的唯一入口点。在下面这个场景中,它告诉了RequireJS在启动的时候加载Main.js。

<!DOCTYPE html>
<html>
<head>
<title>JavaScript RequireJS</title>
<script src="Require.Js" type="text/javascript" data-main="Main.js"></script>
</head>
<body>
<strong>Display data using RequireJS</strong>
<p id="message" />
</body>
</html>

Main.JS

由于这个文件已经通过data-main属性指定,RequireJS将会尽快的加载它。这个文件使用了RequireJS框架的函数来确定和定义对于其它JavaScript文件的依赖关系。在下面的代码片段里,第一个参数表示依赖关系(依赖Order.JS文件),第二个参数为一个回调函数。RequireJS分析所有的依赖关系并载入它们,然后执行这个回调函数。请注意,第一个参数的值(Order)必须和文件名一致(Order.JS)。

require(["Order"], function (Order) {
  var o = new Order(1, "Prasad");
  write(o.id + o.customer.name);
});

Order.JS

RequireJS框架提供了一个定义和维护JavaScript文件间依赖关系的简便途径。下面代码中的define函数声明了Customer.JS必须在处理Order回调函数前载入。

define(["Customer"],
function (Customer) {
function Order(id, custName) {
this.id = id;
this.customer = new Customer(custName);
}
return Order;
}
);
Customer.JS

这个文件不依赖于任何其它JavaScript文件,所以define函数的第一个参数的值是一个空数组。

define([],
function () {
function Customer(name) {
this.name = name;
}
return Customer;
}
);

好了,现在用你的浏览器打开这个应用,你将会看到如下的输出。要注意的是RequireJS只载入了必需的JavaScript文件。

 总结

在这篇文章里,我们分析了RequireJS框架是如何处理JavaScript文件间的依赖关系并根据需要载入它们的。它能够帮助开发者写出更松耦合、更模块化且更具有可维护性的代码。

(0)

相关推荐

  • 使用RequireJS优化JavaScript引用代码的方法

    RequireJS是一个提高你的javascript代码速度和质量的有效方法,同时它还让你的代码更容易阅读和维护. 在本文中,我会为你介绍RequireJS和应该如何使用它.我们讨论引入文件和定义模块,甚至还会接触优化方面的知识. 简单的说,require.js是一个脚本载入程序,允许你把你的javascript代码独立成文件和模块,同时管理每个模块间的依赖关系. 引入文件 在开始使用RequireJS前,我们需要先下载它的库和Asynchronous Module Definition(AMD

  • 详解RequireJs官方使用教程

    § 1.使用 § 1.1 加载 JavaScript 文件 RequireJS的目标是鼓励代码的模块化,它使用了不同于传统<script>标签的脚本加载步骤.可以用它来加速.优化代码,但其主要目的还是为了代码的模块化. RequireJS以一个相对于baseUrl的地址来加载所有的代码. 页面顶层<script>标签含有一个特殊的属性data-main,require.js使用它来启动脚本加载过程,而baseUrl一般设置到与该属性相一致的目录. baseUrl亦可通过Requir

  • RequireJS使用注意细节

    RequireJS介绍 RequireJS由James Burke创建,他也是AMD规范的创始人. RequireJS会让你以不同于往常的方式去写JavaScript.你将不再使用script标签在HTML中引入JS文件,以及不用通过script标签顺序去管理依赖关系. RequireJS是一个非常小巧的JavaScript模块载入框架,是AMD规范最好的实现者之一.最新版本的RequireJS压缩后只有14K,堪称非常轻量.它还同时可以和其他的框架协同工作,使用RequireJS必将使您的前端

  • 在ASP.NET MVC项目中使用RequireJS库的用法示例

    RequireJS 是一个前端模块化开发的流行工具,本身是一个Javascript的库文件,即require.js . RequireJs的主要功能: (1)实现js文件的异步加载,避免网页失去响应: (2)管理模块之间的依赖性,便于代码的编写和维护. 前端模块化开发现在有好多的工具,大体上分为两类,一类是像dojo之类的高大全,dojo v1.8之后已经内置了模块化开发组件:另一类是像require.js,sea.js 这种专心做模块化开发的工具. 从模块化划分的规则来区分,主要分为AMD.C

  • 使用RequireJS库加载JavaScript模块的实例教程

    js通过script标签的默认加载方式是同步的,即第一个script标签内的js加载完成后,才开始加载第二个,以此类推,直至js文件全部加载完毕.且js的依赖关系必须通过script的顺序才能确保:而在js加载期间,浏览器将停止响应,这大大影响了用户体验,基于此,很多解决js以来和加载的方案出现,require js就是其中之一. requirejs加载的模块,一般为符合AMD标准的模块,即用define定义,用ruturn返回暴露方法.变量的模块:requirejs也可以加载飞AMD标准的模块

  • RequireJs的使用详解

    一.为什么使用RequireJS? <script src="a.js"></script> <script src="b.js"></script> <script src="c.js"></script> 上述多个js文件加载的时候,浏览器会停止网页渲染(JS阻塞浏览器渲染),加载文件越多,网页失去响应的时间就会越长:另外各文件的依赖关系很难管理. RequireJs的作

  • 在Html中使用Requirejs进行模块化开发实例详解

    在前端模块化的时候,不仅仅是js需要进行模块化管理,html有时候也需要模块化管理.这里就介绍下如何通过requirejs,实现html代码的模块化开发. 如何使用requirejs加载html Reuqirejs有一个text的插件,它可以读取指定文件的内容,读取到的内容就是文本. 如何下载text插件 第一种方法,可以通过npm下载: npm install requirejs/text 第二种方法,也可以直接去官方github上面直接下载. 直接拷贝内容到text.js中即可. 如何安装t

  • 在JavaScript应用中使用RequireJS来实现延迟加载

    无论简单还是复杂的Web应用,都由一些HTML.JavaScript.CSS文件组成.通常开发者会通过JQuery.Knockout.Underscore等等这样的第三方JavaScript框架来提高开发速度.由于这些JavaScript框架都针对特定的用途开发而且已经得到了"验证",所以直接使用它们就比自己从头实现所需要的功能显得更为合适.然而,伴随着应用的复杂度不断上升,写出干净.低耦合.可维护的代码变得越来越重要.在这篇文章里,我将解释 RequireJS框架如何帮助应用开发者写

  • JavaScript ES6中export、import与export default的用法和区别

    前言 相信很多人都使用过export.export default.import,然而它们到底有什么区别呢? 在看他们之间的区别之前,我们先来看看它们的用法. ES6 import和export的用法 ES6之前已经出现了js模块加载的方案,最主要的是CommonJS和AMD规范.commonjs主要应用于服务器,实现同步加载,如nodejs.AMD规范应用于浏览器,如requirejs,为异步加载.同时还有CMD规范,为同步加载方案如seaJS. ES6在语言规格的层面上,实现了模块功能,而且

  • JavaScript jQuery 中定义数组与操作及jquery数组操作

    首先给大家介绍javascript jquery中定义数组与操作的相关知识,具体内容如下所示: 1.认识数组 数组就是某类数据的集合,数据类型可以是整型.字符串.甚至是对象 Javascript不支持多维数组,但是因为数组里面可以包含对象(数组也是一个对象),所以数组可以通过相互嵌套实现类似多维数组的功能 1.1 定义数组 声明有10个元素的数组 复制代码 代码如下: var a = new Array(10); 此时为a已经开辟了内存空间,包含10个元素,用数组名称加 [下标] 来调用,例如

  • javascript正则表达式中分组详解

    之前写了一篇关于正则新手入门的文章,本以为对正则表达式相对比较了解 但是今天我又遇到了一个坑,可能是自己不够细心的原因吧,今天就着重和大家分享一下javascript正则表达式中的分组.如果你对JS正则表达式不够理解 可以点击这里了解更多. 分组在正则中用的还是比较广的,我所理解的分组 就是一对括号() ,每一对括号 就代表了一个分组, 分组可以分为: 捕获性分组 非捕获性分组 捕获性分组 捕获性分组会在 比如 match exec这样的函数中以第二项,第三项的形式得到相应分组的结果.先来看一个

  • JavaScript 网页中实现一个计算当年还剩多少时间的倒数计时程序

    看到网上这个程序 发现了处错误这里改正了一下: function counter() { var date = new Date(); var year = date.getFullYear(); var date2 = new Date(year, 11, 30, 23, 59, 59); /*转换成秒*/ var time = (date2 - date) / 1000; var day = Math.floor(time / (24 * 60 * 60)) var hour = Math.

  • JavaScript 正则表达式中global模式的特性

    返回 Boolean 值,指出正则表达式使用的global 标志 (g) 的状态.默认值为 false.只读. rgExp.global 必选项 rgExp 参数是正则表达式对象. 如果正则表达式设置了global 标志,那么global 属性返回 true,否则返回 false. 使用 global 标志表明在被查找的字符串中搜索操作将查找所有符合的项,而不仅仅是第一个.这也被称为全局匹配. 一直不是很清楚javascript的global到底表现在哪些方面,所以今天特地做了几个测试: var

  • 在Javascript类中使用setTimeout第1/2页

    最近遇到了一道 Javascript 考题,内容如下: 尝试实现注释部分的 Javascript 代码,可在其他任何地方添加更多 代码(如不能实现,说明一下不能实现的原因): var Obj = function(msg){    this.msg = msg;    this.shout = function(){       alert(this.msg);    } this.waitAndShout = function(){       // 隔五秒钟后执行上面的 shout 方法  

  • javascript函数中执行c#函数的方法

    1如何在JavaScript访问C#函数? 2.如何在JavaScript访问C#变量? 3.如何在C#中访问JavaScript的已有变量? 4.如何在C#中访问JavaScript函数? 问题1答案如下: javaScript函数中执行C#代码中的函数: 方法一:1.首先建立一个按钮,在后台将调用或处理的内容写入button_click中; 2.在前台写一个js函数,内容为document.getElementById("btn1").click(); 3.在前台或后台调用js函数

  • 浅析Javascript ES6中的原生Promise

    前言 一个 Promise 对象可以理解为一次将要执行的操作(常常被用于异步操作),使用了 Promise 对象之后可以用一种链式调用的方式来组织代码,让代码更加直观.而且由于 Promise.all 这样的方法存在,可以让同时执行多个操作变得简单. Promise的兴起,是因为异步方法调用中,往往会出现回调函数一环扣一环的情况.这种情况导致了回调金字塔问题的出现.不仅代码写起来费劲又不美观,而且问题复杂的时候,阅读代码的人也难以理解. 举例如下: db.save(data, function(

随机推荐