写在前面

最早接触javascript的时候,javascript代码直接扔在script标签里面就完事了。

反正代码不多,交互简单,逻辑不难,和HTML混在一起也未尝不可。

后来交互越来越复杂,代码越多越多了,我们就开始把JS代码独立到了单独的JS文件中。

公共的库引用在前,自己的逻辑代码引用在后,全局变量定义在HTML内部,在独立JS文件中直接使用变量就好。

我们会经常看到下面这种代码:

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

通过script标签顺序去js管理依赖关系。

阮一峰老师在Javascript模块化编程(三):require.js的用法
一文中总结了这样写法的缺点:

首先,加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长;

其次,由于js文件之间存在依赖关系,因此必须严格保证加载顺序(比如上例的1.js要在2.js的前面),依赖性最大的模块一定要放到最后加载.

当依赖关系很复杂的时候,代码的编写和维护都会变得困难。

而requirejs的诞生便是为了解决这个问题。

requirejs

在官网把requirejs 下载回来之后。使用一般的方法引入:

<script src="js/require.js"></script>

但是这样的方法,还是可能在加载require.js的时候导致网页失去响应。解决方案一般有两种:

  1. 把上面的代码放到网页底部

  2. 使用异步的方法加载,如下:

<script src="js/require.js" defer async="true" ></script>

async属性 表明这个文件需要异步加载,避免网页失去响应。

不过IE下不支持这个属性,只支持defer,所以可以把defer也写上。

加载主模块

在上一步,我们已经引入了require了,那么require怎么知道我们究竟要加载什么东西呢?答案是使用data-main属性。
假设我们的主模块为js/home.js,引入代码应该如下:

 <script src="js/require.js" data-main="js/home"></script>//require.js默认文件后缀为js,所以home.js可以写成home。

接下来我使用58HouseSearch 的代码来讲解一下require的使用。

在此项目里面,重构前大概就是JS变量漫天飞,js文件里面各种函数到处乱放。一开始用起来还没什么,后来加入了更多功能的时候,JS代码维护起来就疼不欲生了。因此托了个小伙伴帮忙使用模块化思想重构了一下JS代码。

上面说了,我们首先需要创建我们的模块,在这个项目里面,主模块叫home.js。

home.js中我们需要配置一下require.config.

require.config({baseUrl: '/DomainJS/',paths: {jquery: "lib/jquery-1.11.3.min","AMUI": "lib/amazeui.2.7.1.min","jquery.range": "lib/jquery.range","es5": "lib/es5","mapController": "mapController","addToolbar": "addToolbar",},shim: {"addToolbar": {deps: ["jquery"]},"jquery.range": {deps: ["jquery"]}}
});

在这里我主要配置了一下baseURL(所有模块的查找根路径),paths(名称映射),shim(
为那些没有使用define()来声明依赖关系、设置模块的”浏览器全局变量注入”型脚本做依赖和导出配置。)

关于require.config的详细内容可以看下下面这些文章:

  1. RequireJS进阶:配置文件的学习
  2. RequireJS进阶:模块的优化及配置的详解

配置做完了,我们也可以开始真正写我们的逻辑代码了,我们使用require来加载我们需要的库。
代码如下:

require(['domready!', 'jquery', 'AMUI', 'mapController', 'city', 'commuteGo'], function (doc, $, AMUI, mapController, city, commuteGo) {city.initAllCityInfo();mapController.init();$("input[name='locationType']").bind('click', mapController.locationMethodOnChange)$("input[name='vehicle']").bind('click', commuteGo.go)$('#Get58Data').bind('click', function(e) {e.preventDefault();mapController.Get58DataClick();e.stopPropagation();});$.ajax({type: "post",url: "../Commom/GetPVCount",data: { },success: function (result){if (result.IsSuccess){$("#lblPVCount").text(result.PVCount);}else {$("#lblPVCount").text(0);console.log(result.Error);}}});$('#search-offcanvas').offCanvas({ effect: 'overlay' });$(".amap-sug-result").css("z-index", 9999);
})

忽略function里面的具体逻辑,加载如下:

require(['domready!', 'jquery', 'AMUI', 'mapController', 'city', 'commuteGo'],
function (doc, $, AMUI, mapController, city, commuteGo){//todo});

第一个参数为一个数组,表示所依赖的模块,此处为[‘domready!’, ‘jquery’, ‘AMUI’, ‘mapController’, ‘city’, ‘commuteGo’];

第二个参数为回调函数,当前面指定的模块都全部加载成功之后,便调用此函数。加载的模块会以参数形式传入此函数,从而在回调函数内部就可以使用这些模块啦。

require()异步加载所需模块的时候,此时浏览器并不会失去响应;当前面的模块加载成功之后,执行回调函数才会运行我们的逻辑代码,因此解决了依赖性问题。

讲完了模块加载,我们下面讲一下模块编写。

AMD模块编写

require.js加载的模块的采用的AMD规范。所以我们的模块必须按照AMD的规定来写。

关于AMD规范详情可以看这个文章:Javascript模块化编程(二):AMD规范

模块有两个情况,不依赖其他模块和依赖其他模块。

不依赖其他模块

直接define定义,使用function回调。

58HouseSearch/DomainJS/helper.js

define(function () {//获取URL中的参数var getQueryString=  function (name) {var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");var r = window.location.search.substr(1).match(reg);if (r != null) return unescape(r[2]); return null;}return {getQueryString: getQueryString,};
})

依赖其他模块

define中如同require一样,用数组表明需要加载的模块,function回调。

58HouseSearch/DomainJS/marker.js

define(['mapSignleton', 'city', 'transfer'],
function(mapSignleton, city, transfer) {var _map = mapSignleton.map;var _workMarker = null;var _markerArray = [];var load = function(x, y, locationName) {_workMarker = new AMap.Marker({map: _map,title: locationName,icon: 'http://webapi.amap.com/theme/v1.3/markers/n/mark_r.png',position: [x, y]});}var add = function(address, rent, href, markBG) {new AMap.Geocoder({city: city.name,radius: 1000}).getLocation(address, function(status, result) {if (status === "complete" && result.info === 'OK') {var geocode = result.geocodes[0];var rentMarker = new AMap.Marker({map: _map,title: address,icon: markBG ? 'IMG/Little/' +markBG : 'http://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',position: [geocode.location.getLng(), geocode.location.getLat()]});_markerArray.push(rentMarker);rentMarker.content = "<div><a target = '_blank' href='" + href + "'>房源:" + address + "  租金:" + rent + "</a><div>"rentMarker.on('click', function(e) {transfer.add(e, address);});}})};var clearArray = function() {if (_markerArray && _markerArray.length > 0) _map.remove(_markerArray);_markerArray = [];}var clear = function() {if (_workMarker) {_map.remove(_workMarker);}}return {load: load,add: add,clearArray: clearArray,clear: clear};
});

这样的话,一个供require调用的模块也就写好了。

最后感谢小伙伴Larry Sean 帮忙重构代码。

全文完。

使用requirejs编写模块化代码相关推荐

  1. 在Html中使用Requirejs进行模块化开发

    在前端模块化的时候,不仅仅是js需要进行模块化管理,html有时候也需要模块化管理.这里就介绍下如何通过requirejs,实现html代码的模块化开发. 如何使用requirejs加载html Re ...

  2. html编写组织结构,编写模块化的CSS:CSS文件组织结构

    在之前两篇文章中我们已经讨论过如何使用BEM和Namespace来编写模块化的CSS.这篇文章中,我想避开把CSS选择器作为CSS文件结构和组织的依据的方法. 如果你思考过关于什么是文件组织的最佳实践 ...

  3. 第1课第4.4节_Android硬件访问服务编写HAL代码

    android应用如何访问C库 - 落魄影子 - 博客频道 - CSDN.NET  http://blog.csdn.net/ab198604/article/details/51249303 And ...

  4. html5编写网页代码_freeCodeCamp.org的未来-从向世界传授语言到编写代码的5年经验...

    html5编写网页代码 freeCodeCamp went live in October 2014. In the five years since, we've done quite a bit. ...

  5. java培训教程分享:Java编写软件代码自动提示功能

    本期的java培训教程分享主要是介绍的java编写软件代码的一个自动提示功能,很多零基础和初学java的同学们对这一块还不是很了解,Eclipse for android 实现代码自动提示智能提示功能 ...

  6. 编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量,那么下列说法正确的是

    多选 编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量,那么下列说法正确的是:答案在文末 A. Border,边界值测试,包括循环边界.特殊取值.特殊时间点.数据顺序等. B. Corre ...

  7. 编写优质代码的 6 大关键方法

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自|机器学习实验室 [译者注]作为一名开发者,编写一手干净的 ...

  8. 如何优雅的编写 JavaScript 代码

    几乎每个大一点公司都有一个"运行时间长,维护的工程师换了一批又一批"的项目,如果参与到这样的项目中来,大部分人只有一个感觉--"climb the shit mounta ...

  9. 你解决的问题比你编写的代码更重要!

    软件的目的有时会被遗忘 程序员似乎忘记了软件的真正目的,那就是解决现实问题. 50年前,在1968年,由北约科学委员会主办的软件工程工作会议召开.那时,人们开始注意到软件正在成为社会的基本组成部分.然 ...

最新文章

  1. 2021年大数据Flink(三十一):​​​​​​​Table与SQL案例准备 依赖和​​​​​​​程序结构
  2. java json发送文件_关于java:REST API设计在同一请求中将JSON数据和文件发送到api...
  3. 博士申请 | 日内瓦大学招收机器学习和计算机视觉博士生(年薪35万)
  4. Rinne Loves Data Structure
  5. AOP埋点从入门到放弃(二)
  6. 我的世界无人维护的服务器,我的世界:如何进入9年无人管理的2B2T?全球最大战争服务器!...
  7. C语言实现AES加密解密
  8. Java 字符串拼接的各种玩法
  9. java生成三角网_源码:基于离散点的构TIN算法(三角网)
  10. 亿级Web系统负载均衡几种实现方式
  11. 两个股市真理之间的矛盾
  12. 《二》Android 数据库 SQlite SQLiteOpenHelper
  13. 信号的概念以及网络布线
  14. Javascript:创建对象的方式
  15. Android USBCamera投屏 - 利用UVC协议将手机上的画面有线投屏到Android车机的屏幕上
  16. access2016与mysql_Access 2016数据库应用与开发
  17. xv6 risc-v file system logging layer
  18. zmap启动报错:[FATAL] get-iface-ip: ioctl failure: No such device
  19. IEEE 802.15.4的信道接入机制一基础、信标和非信标帧网络
  20. 神经网络控制与matlab仿真,神经网络matlab代码程序

热门文章

  1. 微信公众平台升级9大高级接口功能解读
  2. Mysql增删改查|SQL语句(史上最全|实战教学)
  3. HCIA课程学习笔记
  4. ansys 内聚力模型_基于内聚力模型(CZM)的单筋拉拔数值分析方法研究
  5. 使用AD绘制stm32最小系统版
  6. 《认知觉醒》:第一章 大脑——一切问题的起源
  7. MYSQL 本地计算机上的MySQL服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止
  8. jquery 终止循环,如何解决jquery each循环中终止本次循环或者跳出循环?
  9. 用python教你计算定投能获得多少收益
  10. HTML5 入门 之b u i 标签