模块化方式
什么是模块化
所谓的模块化开发就是封装细节,提供使用接口,彼此之间互不影响,每个模块都是实现某一特定的功能。模块化开发的基础就是函数
-
函数封装
- "污染"了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。
-
对象方式
var module1 = { _count : 0, m1 : function (){ //... }, m2 : function (){ //... } } // 这样的写法会暴露所有模块成员,内部状态可以被外部改写。比如,外部代码可以直接改变内部计数器的值。module1._count = 1;
-
IIFE
var module1 = (function(){ var _count = 0; var m1 = function(){ //... }; var m2 = function(){ //... }; return { m1 : m1, m2 : m2 }; })();
-
放大模式
- 如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用"放大模式"(augmentation)。在原有的基础上扩展更多的方法
var module1 = (function (mod){ mod.m3 = function () { //... }; return mod; })(module1); // 上面的代码为module1模块添加了一个新方法m3(),然后返回新的module1模块,方便方法连续调用。如何防止module1为null或underfined的情况了?
-
宽放大模式
- 在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载。如果采用上面的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用"宽放大模式"。
var module1 = (function (mod){ return mod; })(window.module1 || {}); // 确保对象不为空 // 与"放大模式"相比,"宽放大模式"就是"立即执行函数"的参数可以是空对象,解决了非空问题。
-
输入全局变量
- 独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互。为了在模块内部调用全局变量,必须显式地将其他变量输入模块。
var module1 = (function ($, YAHOO) { //... })(jQuery, YAHOO);
COMMONJS 服务器端同步加载
- 再来说说 module.exports 和 exports,用法其实是相似的,但是不能对 exports直接赋值,不会有任何效果。
- 对于 CommonJS 和 ES6 中的模块化的两者区别是:
- 前者支持动态导入,也就是 require(${path}/xx.js),后者目前不支持,但是已有提案
- 前者是同步导入,因为用于服务端,文件都在本地,同步导入即使卡住主线程影响也不大。而后者是异步导入,因为用于浏览器,需要下载文件,如果也采用导入会对渲染有很大影响
- 前者在导出时都是值拷贝,就算导出的值变了,导入的值也不会改变,所以如果想更新值,必须重新导入一次。但是后者采用实时绑定的方式,导入导出的值都指向同一个内存地址,所以导入值会跟随导出值变化
- 后者会编译成 require/exports 来执行的
AMD (Asynchronous Module Definition)
"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
require([module], callback);
requirejs的使用
-
为什么要使用requirejs
-
加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长;
-
由于js文件之间存在依赖关系,因此必须严格保证加载顺序(比如上例的1.js要在2.js的前面)
-
依赖性最大的模块一定要放到最后加载,当依赖关系很复杂的时候,代码的编写和维护都会变得困难。
-
requirejs 特性
- 实现js文件的异步加载,避免网页失去响应;
- 管理模块之间的依赖性,便于代码的编写和维护。
-
-
requireJs的加载
<script src="js/require.js" data-main="js/main"></script> 1. data-main属性的作用是,指定网页程序的主模块。 2. 在上例中,就是js目录下面的main.js,这个文件会第一个被require.js加载。 3. 由于require.js默认的文件后缀名是js,所以可以把main.js简写成main。
-
主模块的写法
主模块",意思是整个网页的入口代码。它有点像C语言的main()函数,所有代码都从这儿开始运行。下面就来看,怎么写main.js。
require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){ // some code here // require.js会先加载jQuery、underscore和backbone,然后再运行回调函数。主模块的代码就写在回调函数中。 }); /* require()函数接受两个参数。 第一个参数是一个数组,表示所依赖的模块,上例就是['moduleA', 'moduleB', 'moduleC'],即主模块依赖这三个模块; 第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。 */
网友评论