用RequireJS包装AjaxChart

前面我写到AjaxChart,写到SchoolBox,我都在用javascript模拟“类”,提供一些接口让对象使用起来更加方便。javascript中的prototype和闭包、回调等等机制,可以完全用来实现“类”的封装。然而随着“类”规模的不断庞大,类中需要的依赖越来越复杂,如何有效的管理依赖关系也就成了一个问题。而RequireJS就是用来模拟“package”的,以管理“包”中的依赖。

问题由来

在上一篇写AjaxChart,它只是在Highcharts做了层包装,所以依赖于Highcharts,而Highcharts又依赖于jQuery,因此html引入的<script>会像这样。

1
2
3
4
5
6
<script type="text/javascript" src="http://cdn.staticfile.org/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="http://cdn.staticfile.org/highcharts/4.0.4/highcharts.js"></script>
<script type="text/javascript" src="AjaxChart.js"></script>
<script type="text/javascript">
// main程序
</script>

js的引入顺序一定要按照这个顺序,最后才是main程序。当程序越来越复杂时,它就需要更多的依赖,而依赖的对象本身之间可能又存在着依赖,这样到一定程度后依赖关系就会变得很头疼。

RequireJS

RequireJS是继jQuery以来前端界发生的最大成就之一,用于客户端的模块管理,它是符合AMD规范(Asynchronous Module Definition)的。而关于为何要采用AMD规范来写代码,可以看这篇Writing Modular JavaScript With AMD, CommonJS & ES Harmony。RequireJS的基本思想就是,通过define方法,将代码定义为模块,而通过require方法,实现代码的模块加载。

调整代码结构

1. requirejs配置

由于要依赖jQuery和Highcharts,我们先配置好。

1
2
3
4
5
6
7
8
9
10
11
12
13
requirejs.config({
baseUrl: 'js/lib',
paths: {
jquery: 'http://cdn.staticfile.org/jquery/1.7.2/jquery.min',
highcharts: 'http://cdn.staticfile.org/highcharts/4.0.4/highcharts'
},
shim: {
highcharts: {
deps: ['jquery'],
exports: 'Highcharts'
}
}
});

这里jqueryhighcharts均采用的是CDN上的,由于highcharts不是用define写的,所以要加一条shim来做转化。

2. 定义AjaxChart模块

1
2
3
4
5
define(['jquery', 'highcharts'], function($, Highcharts){
// 以上省略...

return AjaxChart;
});

AjaxChart依赖于jqueryhighcharts,最后返回AjaxChart对象。注意这里的文件名也要是AjaxChart.js

3. 执行main程序

1
2
3
requirejs(['jquery', 'highcharts', 'AjaxChart'], function($, Highcharts, AjaxChart){
// 省略...
});

把这段程序放在main.js中,最后在页面中引入<script type="text/javascript" src="js/require.js" data-main="js/app/main.js"></script>即可。

附上目录结构

1
2
3
4
5
6
7
- demo.html
- js/
- require.js
- lib/
- AjaxChart.js
- app/
- main.js

最后demo

AjaxChart with RequireJS Demo