1、模块:类比于java里面包的概念
一个模块就是实现特定功能的文件,模块化开发就是想要什么功能就加载什么模块
2、模块的发展历程:
函数封装
对象:把所有模块成员封装在对象中,调用就对象.方法(缺点外部可以随意更改对象内部的值)
立即执行函数:这样外部就无法修改我们没有露出来的变量和函数,这也是模块化的基础
3、CommonJS:
(1)定义模块:一个文件就是一个模块,一个模块就是一个作用域
(2)模块输出:module.exports对象,输出的内容放入该对象
(3)加载模块:require方法,读取文件并执行,返回文件内部的module.exports对象
(4)尴尬的浏览器,require是同步的,模块系统需要同步读取模块文件内容,并编译执行以得到模块接口,浏览器端,加载JavaScript最佳、最容易的方式是在document中插入script标签,但脚本标签天生异步,传统CommonJS模块在浏览器环境中无法正常加载。
(5)解决思路是用一套标准模板来封装模块定义,但是对于模块应该怎么定义和怎么加载,又产生的分歧:AMD和CMD
4、AMD:异步模块定义的意思,在浏览器端模块开发的典范——RequireJS
(1)RequireJS主要解决2个问题:多个js文件可能有依赖关系,被依赖的文件需要早于依赖它的文件加载到浏览器;js加载的时候浏览器会停止页面渲染,加载文件越多,页面失去响应时间越长
(2)requireJS语法:define(id,[依赖的模块名数组],模块初始化要执行的函数或对象)定义
(3)页面加载:require([所依赖的模块数组],回调函数);加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块
require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。
5、AMD与CMD区别:
(1)最明显的区别就是在模块定义时对依赖的处理不同:AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块;CMD推崇就近依赖,只有在用到某个模块的时候再去require
(2)AMD和CMD最大的区别是对依赖模块的执行时机处理不同,注意不是加载的时机或者方式不同。都是异步加载模块,AMD在加载模块完成后就会执行该模块,所有模块都加载执行完后会进入require的回调函数,执行主逻辑,这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行。CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的。这也是很多人说AMD用户体验好,因为没有延迟,依赖模块提前执行了;CMD性能好,因为只有用户需要的时候才执行的原因。
6、理解JS中的模块规范
(1)函数封装放入util.js,容易命名冲突
(2)参照java引入命名空间
(3)Yui的沙箱机制,已经类似于require了,但是引入多个模块时,无法解决方法到底是那个模块提供的问题
(4)开发通用组件时繁琐的文件依赖关系
(5)命名冲突和文件依赖,是前端开发过程中的两个经典问题。模块化开发主要就是为了解决这2个问题
7、AMD规范诞生的背景:
require是同步的,这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于"假死"状态。因此,浏览器端的模块,不能采用"同步加载",只能采用"异步加载"。这就是AMD规范诞生的背景。
8、requireJS的使用
(1)加载引用文件方式:defer、async="true",表明文件异步加载
(2)data-main="js/main"属性指定网页程序的主模块,类似C或Java语言中main函数的功能
(3)主模块写法:
主模块依赖于其他模块,使用AMD规范定义的require()函数
require([A,B,C依赖模块数组],function(A,B,C模块以参数传入回调函数){})
(4)模块的加载:
require.config()方法,对模块的加载行为进行自定义。
require.config()写在主模块(main.js)的头部。参数就是一个对象,这个对象的paths属性指定各个模块的加载路径。
逐一制定路径、或指定基路径(baseUrl)、还可以直接指定网址
(5)模块的写法:define()函数
不依赖其他模块写法、依赖其他模块的写法
(6)加载非规范模块:
require.config()方法的shim属性,专门用来配置不兼容的模块。具体来说,每个模块要定义:1、exports值(输出的变量名),表明这个模块外部调用时的名称;2、deps数组,表明该模块的依赖性。
(7)一系列插件:domready、text、image、json等