模块化

*解析

模块是可以实现特定功能的一组代码。

由于JS不能handle超大规模代码,所以要借鉴其它语言处理这种问题的方式:
把逻辑相关的代码组织到同一个区域,区域内部相对独立和外界互不干扰;
外部使用时直接引用对应的区域即可。

模拟类似的功能,用来隔离、组织复杂的JavaScript代码,我们称为模块化。

*作用

1 解决命名冲突
2 解决互相依赖
3 提高代码的可读性
4 提高代码的复用性

*规范

**CommonJS

解析:
服务器端使用的模块规范 例如 Node.js

使用:
1 定义模块 一个文件 = 一个模块 = 一个单独的作用域
2 模块输出: 唯一出口module.exports对象,存放输出内容
3 加载模块: 使用require方法读取文件并执行,返回ta内部的module.exports对象

举例:                      
  
Model-1.js                    1 定义模块
    var name = 'jrg';           
    function a(){...}             name是模块的内部变量,只有文件内的函数可以使用
    function b(){...}                            
    module.exports={          2 模块输出 (导出接口)
        a:a,
        b:b
    }

Model-2.js                        *新模块 = 新文件
    function c(){...}
    module.exports = c


main.js                       3 加载模块                              
    var xx = require('./Model-1');
    var dd = require('./Model-2');  使用哪个模块再引入                        
    xx.a()                      
    dd.c()                          然后就可以调用模块提供的方法

**问题

Q CommonJS 规范在服务器端这么方便,那么浏览器端可以用吗?
A NO!
R 服务器端的文件在本地 => 同步加载;浏览器端的文件在远程服务器 =>异步加载
····所以CommonJS模块在浏览器环境中无法正常加载。
····浏览器端需要另外的规范来封装模块 => AMD & CMD

**AMD

解析:
浏览器端使用的模块规范之一 Asynchronous Module Definition异步模块定义

define函数,定义模块-------------------------------------------------- 

语法: 
    define(id?, dependencies?, factory)

参数:
    id:模块名;如果没有参数,默认为文件名。
    dependencies:一个数组;当前模块 [依赖的模块名称集合]。
    factory:工厂函数;模块初始化要执行的函数(只执行一次) or 对象(模块的输出值)。


 require函数,加载模块-------------------------------------------------

 语法:  require([dependencies], function(){});

 参数:  [dependencies]是一个数组,表示所依赖的模块;
         function(){} 是一个回调函数,当前面指定的模块都加载成功后,以参数形式传入该函数,
                      然后函数内部就可以使用这些模块了。

 
 举例----------------------------------------------------------------------------

 myModule1.js    定义模块 
     define(['dependency'], function(){      
         function a(){...} // 使用面向对象方式封装好的组件
         return a,        //  留出接口
     });

 main.js      加载模块  
     require(['myModule1','myModule2'], function (myModule1,myModule2){    
          myModule1.a();      // 调用组件
     });

**CMD

解析:
国内发展出来的模块规范Common Module Definition通用模块定义

define函数,定义模块---------------------------------------------------------

语法:               
    define(function(require, exports, module){ });

参数:    
   require 是一个方法,获取其他模块的接口
   exports 是一个对象,向外提供模块接口
   module 是一个对象,存储了一些属性和方法

举例--------------------------------------------------------------------------

 ModuleA.js     定义模块 
   define(function(require, exports, module) {    function的三个参数固定不变 
     var a = require('a.js')                       函数内部,用到谁就引入谁
     a();                                          写法类似commonJS
     ModuleA.exprots = xx;
   });

main.js       加载模块  
   seajs.use(['ModuleA.js'], function(ModuleA){ ... });

模块化工具:
▶由于不是JavaScript原生支持,
使用AMD需要用到对应的库函数RequireJS
使用CMD需要用到对应的库函数SeaJS
其实AMDCMD分别 是RequireJSSeaJS 在推广过程中对模块定义的规范化产出;
同样倡导模块化开发理念,核心价值是让 JavaScript 的模块化开发变得简单自然。

AMDCMD的区别?
** 1** 关于依赖的模块,加载都是异步,执行处理不同
AMD:推崇依赖前置,提前执行(依赖先执行)
CMD:推崇依赖就近,延迟执行(运行到需加载,根据顺序执行)
** 2** 关于API
AMD:API根据使用范围有区别,但使用同一个api接口
CMD:每个API的职责单一

**requireJS

requireJS主要解决两个问题:
1 实现js文件的异步加载,避免网页失去响应;
2 管理模块之间的依赖性,便于代码的编写和维护。

如果
   不使用`requireJS`就要单独加载每个js文件,像这样:
   <script src="1.js"></script>
   <script src="2.js"></script>
   <script src="3.js"></script>
 缺点
   1 加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长;
   2 由于js文件之间存在依赖关系,因此必须严格保证加载顺序,依赖性最大的模块必须放到最后,
     当依赖关系很复杂的时候,代码的编写和维护都会变得困难。

**总结

至此,已经了解模块规范,可以写出符合规范的 模块文件了!
以AMD为例,梳理一下使用过程:

1 下载require.js文件,放入根目录
2 页面引入requireJS库<script src="http://require.js"></script> => 主文件
3 页面引入主文件 <script src="http://main.js"></script> => 加载模块
4 主文件 => 已放入根目录的模块文件
Tip:
主文件=>加载模块=>require函数=>语法require([dependencies], function(){})
模块文件=>定义模块=>define函数=>语法define([dependencies], factory)

**r.js

这是一个打包工具

作用
把所有的模块和框架js文件压缩到同一个js文件里,
Before: 引入requireJS库=>引入主文件=>查找模块
After : 引入requireJS库=>查找模块

使用
1 下载r.js文件,放入根目录
2 配置压缩文件build.js
3 打开node,进入目标DEMO-AMD
4 执行命令行node r.js -o build.js,会自动生成压缩文件
5 将页面上的主文件地址main.js替换为压缩后的文件index.merge.min.js

*应用

Demo

▼DEMO-AMD   
   ▶index.html   
   ▶CSS              
   ▼JS
     ▼lib            框架&库目录
       ▷require.js
       ▷r.js
       ▷jquery.js
        ......
     ▼app            组件目录
       ▷gotop.js
        ......
     ▶main.js       主文件
     ▶build.js      压缩配置文件

     ▼dist          输出目录
       ▷index.merge.min.js   


   ■ index.html
    页面加载 <script src="http://js/lib/require.js" data-main="js/main.js"></script>
    □ src       先加载库 => 执行require.js => 解析后指向主文件  
    □ data-main 自定义属性 => 执行main.js  =>  主文件里是所有模块的入口


   ■ main.js                主文件 =>
     requirejs.config({              □ 配置路径,方便查找
         baseUrl: "./js/app",             默认文件夹(加载时写直接写里面的模块名)
         paths: {                         特殊文件/夹(相对于baseUrl)
             'jquery': '../lib/jquery'        指向模块  (加载时写模块名)
             'lib':'../lib'                   指向文件夹(加载时写lib下模块名)
         }                                  
     });
     requirejs(["GoTop","lib/xx",...],
     function(GoTop,$,...) {         □ 加载([依赖模块],工厂函数)
         new GoTop();                          模块加载完毕,作为参数传入工厂函数
         ......                                 执行工厂函数
     });

    ● 这里的baseUrl是main.js相对于index.html=> 从index出发找到app
    ● requirejs(["xxx"]) => 如果没有工厂函数,直接加载并执行文件


   ■ build.js             压缩配置文件 =>  
     ({                                □ 配置路径   
         baseUrl: ".",                       两个baseUrl指向要保持一致(都指向app)  
         paths: {
             'jquery': './lib/jquery',
             'GoTop':'./com/GoTop',
             ......
         },
         name: "main",                       配置入口
         out: "./dist/index.merge.min.js"    配置出口(自定义)
     });

    ● 这里的baseUrl是build.js相对于自身的,=> 从build 出发找到 app

参考 详解JavaScript模块化开发

但是!程序员永远有更便捷的方法 => webpack

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,681评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,710评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,623评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,202评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,232评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,368评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,795评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,461评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,647评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,476评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,525评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,226评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,785评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,857评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,090评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,647评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,215评论 2 341

推荐阅读更多精彩内容

  • 什么是模块化开发? 前端开发中,起初只要在script标签中嵌入几十上百行代码就能实现一些基本的交互效果,后来js...
    半世韶华忆阑珊阅读 647评论 0 0
  • 原文链接:http://www.cnblogs.com/lvdabao/p/js-modules-develop....
    舌尖上的大胖阅读 694评论 0 1
  • 在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升...
    简不简单_都好阅读 217评论 0 0
  • 前端模块化 在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到...
    景岳阅读 240评论 2 4
  • 楚汉之争中豪杰并出,有勇之人有谋之人纷纷投靠两位争执不休的楚王与汉王,而韩信便在这场战争中问事了,他效忠于刘邦,创...
    无端若梦阅读 459评论 0 0