基于RequireJS和JQuery的模块化编程——常见问题全面解析
由于js的代码逻辑越来越重,一个js文件可能会有上千行,十分不利于开发与维护。最近正在把逻辑很重的js拆分成模块,在一顿纠结是使用requirejs还是seajs的时候,最终还是偏向于requirejs。毕竟官方文档比较专业嘛...
不过即便是有完整的官方文档,仍然遇到不少的问题,比如jquery-ui的使用。
下面就循序渐进的讲解一下我遇到的问题,以及解决的办法。
关于AMD和CMD的理解
AMD(异步模块定义)的典型就是requirejs,而CMD(通用模块定义)的典型是淘宝的seajs。
他们的相同点是,都会异步的加载js。但是不同点是,require.js加载完会立即执行;而seajs则是等到进入主函数需要执行时才执行。
如果使用seajs初始的加载执行效率会比较高,但是在使用的过程中可能会取执行js,因此可能会出现卡顿,影响用户体验(由于我也没试过,要是说错了,别见怪)。而requirejs则是在一开始就把所有加载的js都执行,这时,如果你的模块中有一些执行方法,它们可能并不会按照你想的顺序执行。
因此,如果已经习惯了异步编程,并且希望有完善的文档推荐使用requirejs;如果是想对执行顺序有特殊要求,又方便开发,那么也可以使用seajs。
如何解决requirejs中循环依赖问题
如果你定义的某个a模块使用到了b模块,而b模块又使用了a模块,那么就会抛出循环依赖的异常。
比如,我这里写了一个循环依赖的例子。
主页面:
<!DOCTYPE html> <html> <head> </head> <body> <script data-main="test.js" src="lib/require.js"></script> </body> </html>
主方法:
requirejs.config({ baseUrl: './' }); requirejs(['js/a'],function (a){ console.log("in test"); a.testfromb(); });
a.js模块中,atest()方法提供b调用、testfromb()方法调用b的方法
define(function(require){ var b = require("js/b"); console.log("in a"); return { atest:function(){ console.log("test in a"); }, testfromb:function(){ console.log("testfromb in a"); b.btest(); } } });
b模块中,调用了a的方法。
define(function(require){ var a = require("js/a"); console.log("in b"); return { btest:function(){ console.log("test in b"); a.atest(); } } });
这样相当于a调用了b的方法,但是b的方法依赖于a的方法,这就造成了循环依赖。浏览器会提示错误:
Uncaught Error: Module name "js/a" has not been loaded yet for context: _
按照官方文档的说法,这种属于设计的问题,应该尽量避免。那么如果避免不了该怎么办呢?可以这样修改b模块:
define(function(require){ // var a = require("js/a"); console.log("in b"); return { btest:function(){ console.log("test in b"); require("js/a").atest(); } } });
这里是等到执行atest()方法时,才加载a模块。这时,a模块很显然已经加载完了 。可以看到输出的信息:
in b a.js:3 in a test.js:6 in test a.js:9 testfromb in a b.js:6 test in b a.js:6 test in a
同样的方式,修改a可能就不好使了。这时因为模块加载的顺序是从b开始的。
关于循环依赖的源码可以参考云盘
如何在requirejs中使用jquery
如果想要使用jquery比较简单,直接在main.js中添加对应的依赖即可:
requirejs.config({ baseUrl: './', paths:{ 'jquery':'lib/jquery' } }); requirejs(['jquery'], function ($){ $('#test').html('test'); });
如何在requirejs中使用jquery插件 对于jquery的插件,比较常见的做法都是传入一个jquery的对象,在这个jquery对象的基础上添加插件对应的方法。 首先需要添加jquery插件的依赖,这里用两个插件举例子——jquery-ui和jquery-datatables
requirejs.config({ baseUrl: './', paths:{ 'jquery':'lib/jquery', 'jquery-ui':'lib/jquery-ui', 'jquery-dataTables':'lib/jquery.dataTables' }, shim:{ 'jquery-ui':['jquery'], 'jquery-dataTables':['jquery'] } }); requirejs(['jquery','jquery-ui','jquery-dataTables'], function ($){ .... });
由于jquery插件都需要依赖于jquery,因此可以在shim中指定依赖关系。 除了上面这种使用方法,也可以使用commonJS风格的调用:
define(function(require){ var $ = require('jquery'); require('jquery-ui'); require('jquery-dataTables'); //下面都是测试,可以忽略 var _test = $('#test'); _test.selectmenu({ width : 180, change : function(event, ui) { console.log('change'); } }); return { test:function(){ //测试jquery-ui _test.append($('<option>test1</option><option>test1</option>')); _test.selectmenu("refresh"); //测试jquery-datatables var _table = $('table'); _table.dataTable(); } } });
不过,执行上面的代码,会报一个异常:
Uncaught TypeError: _table.dataTable is not a function
这是因为,dataTables并不是一个require风格的模块,因此直接这样引入,并不会执行它内部的匿名函数。可以修改它的匿名函数,传入$对象,在最后一行:
*/ return $.fn.dataTable; //}));原来是这样 }($)));//这里增加执行这个匿名函数,并且传入$对象。 }(window, document));
这也是在网上搜的方法,原理奈何经验不足....
样例代码可以参考云盘,由于引入的资源不是很全,所以会报错,可以直接忽略,因为能执行UI插件就表示已经成功了。
requirejs使用jquery-ui的问题
由于requirejs加载js文件后会立即执行,如果你的jquery ui 插件需要刷新DOM页面,那么可能会导致页面的事件失效。
比如,你的模块在加载后,对页面的某个元素$('#test')绑定了click事件。但是使用了某个UI插件,这个插件会重新渲染DOM元素,test对应的click事件就失效了。
解决办法:
•把事件绑定推迟到DOM元素渲染完后再手动触发绑定;
•也可以使用事件捕获代替DOM元素的事件绑定(太麻烦了...不推荐)。
比如在DOM重构的JS模块中,执行渲染的代码下面:
require("xxx").initEvents();常见场景:
比如我在页面中使用了jquery-steps这个UI插件,它会对页面进行重新渲染。这就导致我最开始绑定的事件都失效了....只有推迟到这个js重构完页面,再绑定才行。
以上这篇基于RequireJS和JQuery的模块化编程——常见问题全面解析就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
- Query架构的开发人员能够创建一个插件代码来扩展其功能,从而能够产生一些最好的插件,让你的网站或任何给定的项目达到一个全新的水平。 ...2016-04-27
- 这篇文章主要介绍了BootStrap和jQuery相结合实现可编辑表格的相关资料,需要的朋友可以参考下...2016-04-23
基于RequireJS和JQuery的模块化编程——常见问题全面解析
下面小编就为大家带来一篇基于RequireJS和JQuery的模块化编程——常见问题全面解析。小编觉得挺不错的,现在分享给大家,也给大家做个参考...2016-04-17- 本文给大家分享的是如何在Node.js中使用jQuery的方法,包含步骤以及出错的处理,非常的详细,有需要的小伙伴可以参考下...2016-09-01
- 这篇文章主要为大家详细介绍了前端笔记之jquery部分,jQuery是一个兼容多浏览器的javascript库...2016-05-05
- 在Node.js中使用jQuery的做法,需要先安装jquery,npm install jquery ,安装后的版本是 3.1.0,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起看下吧...2016-08-24
- 这篇文章主要介绍了jQuery中通过ajax的get()函数读取页面的方法,需要的朋友可以参考下...2016-03-01
在Web项目中引入Jquery插件报错的完美解决方案(图解)
这篇文章主要介绍了在Web项目中引入Jquery插件报错的完美解决方案的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下...2016-10-03CSS3 media queries结合jQuery实现响应式导航
这篇文章主要为大家详细介绍了CSS3 media queries结合jQuery实现响应式导航,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2016-10-02- 这篇文章主要介绍了基于Bootstrap使用jQuery实现简单可编辑表格的相关资料,需要的朋友可以参考下...2016-05-05
基于Bootstrap使用jQuery实现输入框组input-group的添加与删除
这篇文章主要介绍了基于Bootstrap使用jQuery实现输入框组input-group的添加与删除的相关资料,需要的朋友可以参考下...2016-05-05- 这篇文章主要介绍了JavaScript与jQuery实现的闪烁输入效果,结合实例形式分别分析了JavaScript与jQuery实现闪烁输入效果的方法与具体使用技巧,需要的朋友可以参考下...2016-02-21
- 这篇文章主要介绍了js与jquery正则验证电子邮箱、手机号、邮政编码的方法,涉及javascript与jQuery鼠标事件的响应与正则验证操作字符串的相关技巧,需要的朋友可以参考下...2016-07-06
- 这篇文章主要介绍了详解jQuery UI库中文本输入自动补全功能的用法,其中重点讲解了常用的邮箱地址输入时后缀自动补全功能的使用,需要的朋友可以参考下...2016-04-25
- 这篇文章主要介绍了 JavaScript、jQuery与Ajax的关系的相关资料,需要的朋友可以参考下...2016-01-25
- 这篇文章主要介绍了HTML5中用js、jQuery结合Ajax实现文件上传功能,HTML5中已经可以用Ajax上传文件了,而且代码简单,借助 FormData类即可发送文件数据,感兴趣的小伙伴们可以参考一下...2016-04-19
- 在前端模块化的时候,不仅仅是js需要进行模块化管理,html有时候也需要模块化管理。这里就介绍下如何通过requirejs,实现html代码的模块化开发...2016-04-18
- 这篇文章主要为大家详细介绍了jQuery插件实现可输入和自动匹配的下拉框,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2016-10-25
探索angularjs+requirejs全面实现按需加载的套路
这篇文章主要探索了angularjs+requirejs全面实现按需加载的套路,围绕angularjs提供的各种机制进行研究,感兴趣的小伙伴们可以参考一下...2016-03-01小心!AngularJS结合RequireJS做文件合并压缩的那些坑
小心!AngularJS结合RequireJS做文件合并压缩的那些坑,大家在做文件合并压缩的时候一定要注意,感兴趣的朋友可以参考一下...2016-01-12