关于模块化 - 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

参考