Web前端 之 RequireJS
来源:互联网 发布:深入理解linux内核pdf 编辑:程序博客网 时间:2024/05/01 06:31
引言
随着互联网的发展,浏览器端的应用越来越多,单个应用规模越来越大,逻辑也越来越复杂,从最初的页面动态效果,到与服务器异步通信,以AJAX为代表的通信技术,允许在不刷新页面的情况下动态请求服务器的服务,再到复杂的交互,使得JavaScript代码里剧增,因此,代码如何有效组织容易维护,如何应对规模效应和复杂逻辑,以及需求多变的要求,是前端急需解决的问题。
问题是这样,解决方法有什么呢?从其他比较成熟的桌面端编程语言或者服务器端编程语言,我们可以找出解决方法,因为这些语言或者技术已经经过了这个阶段。比如,面向对象技术,但是直到ES5,JavaScript中并没有面向对象的直接支持,一般的做法是利用JavaScript中的函数,原型链实现;又比如模块化组织代码,直到ES5,JavaScript中也是没有直接支持,这时候出现了很多规范和方法来实现模块化,比如CommonJS,AMD(不是CPU)等。今天我们要说的就是AMD的一个实现:Require.js。
注:当然,模块化并不能代表前端工程化,前端工程化囊括了很多内容:例如,因为网络应用的特殊性,既成的代码压缩后会有更小的体积,这样便更利于网络传输,所以前端工程化还包括流程的自动化,各种优化等问题。本文只介绍模块化中的一个解决方案。
没有Resquire.js时我们遇到的问题
AMD时异步模块定义的缩写,从名字中我们可以看出,其主要特定是模块异步加载,为什么要异步呢?同步有什么缺陷吗?请看下面的例子:
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>不使用RequireJS</title> <link rel="stylesheet" href="css/main.css" media="screen" title="no title" charset="utf-8"> </head> <body> <div id="map" class="map"></div> <script src="scripts/1.js" charset="utf-8"></script> <script src="scripts/2.js" charset="utf-8"></script> <script src="scripts/3.js" charset="utf-8"></script> <script src="scripts/4.js" charset="utf-8"></script> <script src="scripts/5.js" charset="utf-8"></script> <script src="scripts/6.js" charset="utf-8"></script> <script type="text/javascript"> // Do Something </script> </body></html>
这个例子中两点需要指出,1,引入JavaScript都放置于页面底端,这是因为JavaScript执行和UI渲染是使用的一个线程,如果将JavaScript放于传统的`<head></head>`标签中,如果项目比较复杂,JavaScript文件将会引入很多,而加载JavaScript文件时会阻塞UI的渲染,这个时候用户会看到一片空白;2,JavaScript载入是`one by one`,这就意味着,1加载完,2才会加载,这样同步依次加载,显然没有异步加载快速,且考虑到JavaScript模块文件之间的相互依赖,以上例子只能按照一定的顺序执行。
那么我们看看Require.js是如何解决这些问题的。
Require.js模块异步加载
异步加载是指几个JavaScript模块文件共同加载,要使用RequireJS提供的异步加载功能,我们需要将RequireJS引入,我们在html引入的格式如下:
<script data-main="your_script" src="require.js"></script>
data-main属性指定的自己写的JavaScript脚本,该文件不必带.js文件类型后缀,因为RequireJS默认就是认为文件都是JavaScript,这样就可以利用RequireJS提供的模块异步加载功能了。但是共同加载就有一个问题,比如2.js依赖于1.js,怎么确定2.js要执行时,1.js已经加载完了呢?在Requirejs中可以通过'requirejs.config({})'来进行配置,这个配置是写在your_script.js中的,比如我们配置2.js依赖于1.js,如下:
requirejs.config({ shim: { 2: ['1'] }});
这里虽然1.js 与 2.js 同时加载,但是经过这样的配置,一定保证2.js在1.js之前加载完成,这样既保证了加载的速度,又保证了类库之间的依赖关系。requirejs还有很多配置参数,例如下面的例子:
requirejs.config({ urlArgs: 'bust='+(new Date()).getTime(), waitSeconds: 20, baseUrl: 'scripts/libs', paths: { jquery: 'jquery.min', bootstrap: 'bootstrap.min' }, shim: { bootstrap: ['jquery'] }});
默认情况下,Require.js会缓存请求的JavaScript文件,这种情况下,如果对引入的JavaScript代码做了修改,那么你刷新网页,浏览器还是调取缓存的版本,urlArgs会将其值附加到每个请求的JavaScript文件,这样浏览器就会认为JavaScript发生了改变,取最新的版本,而不是缓存的版本。或者你如果你使用firefox,可以crtl+F5可以清空缓存,重新请求,使用chorme,打开控制台,在其刷新按钮处右键鼠标,会弹出选项,是清空缓存重新请求还是从缓存中获取,但这两种方式都不如添加urlArgs方便。
waitSeconds表示加载脚本等待的最长时间,超出指定时间将会报错并停止加载;baseUrl表示JavaScript脚本库的存放路径;paths可以配置脚本独自的特殊路径,例如某个脚本不在规定的baseUrl目录中,可以使用该选项配置;shim参数则配置各个脚本之间的依赖,比如例子中bootstrap的脚本插件依赖jquery,即可这样配置。
Require.js管理与定义模块
RequireJS另外一个重要的功能是它提供了模块化的管理思想,我们从其他的语言或者技术中可以知道,模块一般就是一个文件,一个文件一般只写一个有关的类或者命名空间,JavaScript的命名空间可以使用对象字面量来进行模拟,这里不再延伸。在JavaScript中,我们也要尽量遵循这些思想,那么,每个模块如何引入呢?如何书写呢?AMD都有自己的规定,比如引入,其规定使用require函数,如下:
require(['jquery','bootstrap'], function($){ // here you can use $ for jquery and bootstrap});
require才会真正引发相应的JavaScript载入,requirejs.config({})只是做相关的配置,并不会引发文件载入。require函数接收两个参数,第一个是一个数组,包含所有需要载入的依赖,第二个是相应文件载入后需要调用的回调函数,参数是每个依赖导出的局部变量,比如jquery使用$。这样我们就可以在回调函数的函数体中书写我们的逻辑业务代码了。但是,并不是所有的JavaScript文件都可以通过require([],callback);载入,需要载入的类或者模块必须遵循AMD的模块定义规范。在RequireJS中,定义模块需要使用define函数,如下:
define(['jquery'],function($){ function SomeClass(){ // some code } SomeClass.prototype.subfunction = function(){ // do Something }; SomeClass.prototype.subfunction2 = function(){ // do Something }; return SomeClass;});
define函数的原型是define([],callback),接收两个参数,第一个是可能的依赖库,比如jquery,是一个数组,可以指定多个依赖,使用逗号分开,第二个参数是回调函数,参数与依赖数组对应,表示依赖导出的局部变量,和require函数基本一致,这样增加了一致性,减少了学习成本。你可以在你的模块里,写一个类,或者一个命名空间,或者仅仅是写一些函数的集合,都可以,最后将模块导出时,你可以直接return一个对象或者命名空间,或者一个对象字面量,或者一个函数,如例子中,我们导出了这个类。我们在调用的代码处,便可以直接new来初始化SomeClass类:"var example = new SomeClass();"。
总结
以上就是使用RequireJS在前端模块化给出的解决方案:模块的定义和导出,模块的导入及并行加载。需要指出的是,还有其他的规范对JavaScript的模块化做出的努力,比如CommonJS,Node就遵循这个规范。
好的,就写到这里,有问题欢迎文章下留言或者给我发邮件。
- Web前端 之 RequireJS
- 使用RequireJS优化Web应用前端
- 使用RequireJS优化Web应用前端
- 使用RequireJS优化Web应用前端
- 使用 RequireJS 优化 Web 应用前端
- 使用 RequireJS 优化 Web 应用前端
- 使用RequireJS优化Web应用前端
- 使用 RequireJS 优化 Web 应用前端
- 使用RequireJS优化Web应用前端
- Web前端开发requireJs学习研究(一)
- 使用 RequireJS 优化 Web 应用前端
- 使用 RequireJS 优化 Web 应用前端
- AMD和RequireJS初识----优化Web应用前端
- 【web前端自动化工作环境配置】10. RequireJS总结
- [前端] requireJS—详解
- requirejs前端模块化
- web前端之javascript
- Web前端之基础知识
- map的引用传递浅谈
- UITextView设置文字垂直居中和LinkAttribute
- JSON页面间传值问题
- c# .net orm 框架 dapper.net 的应用
- 总结程序员成长的几个阶段的心态
- Web前端 之 RequireJS
- DiskFileItemFactory类
- 设计师们值得一试的十款用户体验工具
- VS创建Qt4应用程序后如何生成.ui文件的ui_XXX.h文件
- Android四大基本组件介绍与生命周期
- java通过反射得到get、set方法
- 第十三周项目2-动物这样叫(3)
- 3.UDP编程
- dialog源码解析笔记