关于模块化 - TG-FEX/armer GitHub Wiki
关于模块化
armerJS的模块加载器是基于C/AMD作为模型的混合型的加载器,兼容CMD、AMD以及混合模式加载
define 函数
define(name, deps, factory)
- name 定义的模块名
- 该参数可以省略
- 可以在模块名前面添加命名空间以区分不同模块,默认为
"default"
,例如"common:aaa"
- 可以在命名空间或者模块名前面添加处理器以区分不同的处理方式,例如
"tg!common:aaa"
,mvvm!abc
- 模块名可以是url,
common:http://xxx.xx/js.js
- 默认处理器为auto,这一点与rjs不一样,可以直接加载js/html/img/css,模块名可省略js后缀,其他格式文件则不可
- name不是模块的唯一ID,但在相同文件下不允许有相同处理器、相同命名空间的同名模块
- 当有require运行时,遇到加载的模块名为空的模块会当作当前正在请求的模块,如果不为空,则区别命名空间和处理器和模块名,并创建新的模块
- 与rjs不一样的是,如果加载的js到最后没有一个符合的模块,则会把最后一个模块当作正在请求的模块
- deps 该模块依赖那些模块,默认为
['require', 'exports', 'module']
- 没有依赖的情况可以省略
'require'
、'exports'
、'module'
为全局模块,分别返回- require函数
- 当前模块的输出(exports)
- 当前模块
- 上一条具体参考CMD、commonJS
- 依赖是不分先后的,只会按顺序请求,后者不依赖前者的加载情况
- 依赖是字符串组成的数组,字符串为模块名,跟模块名规则一致
- factory 模块体,如果是function则会在依赖加载完成后执行
-
模块体可以是任何类型
-
假如是function,则在依赖完成后执行该function
-
会按照依赖传进每个依赖模块的输出值(exports值)作为参数
define(['a'], function(a){ //a这个参数就是a模块的返回值了 })
-
如果function带返回值,那么这个模块的exports为该值
-
如果没有返回,那么为空的对象
{}
-
模块体依赖中如果包含
'exports'
的话,那么可以通过function对应的exports修改exports -
模块体依赖中如果包含
'module'
的话,那么可以通过function对应的exports修改module -
如果模块类型不是script,那么返回对应的结果
-
如果没有被require的话,factory是不会执行的
-
如果依赖包含
'require'
,那么define函数会分析factory字面量内部调用require的情况,并作为依赖添加到依赖列表内define(function(require, exports, module){ // 这里的依赖会被收集到deps里,预先准备好依赖才执行这个function require('../a') require('../b') require('../c') // 可以通过修改module的exports来修改输出值 module.exports = function(){} // 也可以通过修改exports来调整输出 exports.a = function(){} // [x] 不能直接修改exports exports = {} // 也可以通过返回来修改exports return {} })
-
-
factory 一般也可以输出对象,这个就是JSONP的基本格式
-
当然也可以是任何东西
-
- 不同的模块可以打包为同一个文件,模块间没有先后顺序,程序会按照先后顺序运行
require 函数
require(deps, callback, errCallback)
- deps 请求哪些模块,是一个模块名的数组,具体参考define的deps
- callback 所有依赖加载完成后执行的代码
- errCallback 依赖加载出错后执行
- require会连锁require依赖的依赖,比如require一个main.js,那么只需要定义main模块,那么main模块依赖的模块以及他们的子孙依赖都会被请求并执行
- require可以require未经过模块化处理的js,但是他们不会有exports
让一个JS具有模块化的功能
一般的js可以通过require加载,但是不会具有exports,如果需要让他们模块化,有以下几种做法
-
修改源码,只需要添加一句简单的代码就可以让js具有模块化的能力,并且不影响没有引入define的环境执行
if (typeof define == 'function') define('模块名', function(){return '需要的输出'})
-
使用shim,在你的代码加入如下代码
require.config({ shim: { // 模块名 foo: { // 这个会当作依赖 deps: ['bar'], // 这个会作为exports exports: 'Foo' init: function(foo){ //这个function会被当作factory } } } })
例子
https://github.com/TG-FEX/armer/blob/master/test/require-test/test.html