• 转: seajs手册与文档之--模块定义



    模块定义

    在 SeaJS 中,所有 JavaScript 文件都应该用模块的形式来书写,并且一个文件只包含一个模块。

    define

    使用全局函数 define 来定义模块:

    define(id?, dependencies?, factory);
    

    id

    当前模块的唯一标识。该参数可选。如果没有指定,默认为模块所在文件的访问路径。如果指定的话, 必须是顶级或绝对标识(不能是相对标识)。~~一般由优化工具生成

    dependencies

    当前模块所依赖的模块,是一个由模块标识组成的数组。该参数可选。如果没有指定,模块加载器会从 factory.toString() 中解析出该数组。~~~factory.toString()中用正则匹配require(..),提取依赖模块,所以一般不用传入dependencies

    ** 注意:强烈推荐不要设定 iddependencies 参数。 在开发阶段,模块加载器会自动获取这两个参数。部署上线时,则可以通过优化工具来提取这两个参数。

    factory

    模块的工厂函数。模块初始化时,会调用且仅调用一次该工厂函数。factory 可以是函数, 也可以是对象、字符串等任意值,这时 module.exports 会直接设置为 factory 值。

    factory 函数在调用时,会始终传入三个参数: requireexportsmodule, 这三个参数在所有模块代码里可用。 ~~~factory参数可以为字符串?

    define(function(require, exports, module) {
    
      // The module code goes here
      
    });
    

    exports

    exports 用来向外提供模块的 API.  ~~~注意 module.exports 和 exports指向同一对象, exports不能在模块定义代码中被重写 如 exports = { foo:function(){..}, bar:200 }

    define(function(require, exports) {
      // snip...
      exports.foo = 'bar';
      exports.doSomething = function() {};
    });
    

    除了给 exports 对象增加成员,还可以使用 return 直接向外提供 API.

    define(function(require, exports) {
      // snip...
      return {
        foo: 'bar',
        doSomething: function() {};
      };
    });
    

    如果 return 语句是模块中的唯一代码,可简化为:~~~直接传json到define(json)中

    define({
      foo: 'bar',
      doSomething: function() {};
    });
    

    上面这种格式特别适合定义 JSON 数据。

    ** 注意:下面这种写法是错误的!

    define(function(require, exports) {
      // snip...
      exports = { // 错误!  exports 和 module.exports 无关联了,只是对象字面量而已
        foo: 'bar',
        doSomething: function() {};
      };
    });
    

    模块加载器不能获取到新赋给 exports 变量的值。 请使用 returnmodule.exports

    require

    require 函数用来访问其他模块提供的 API. ~~~用require函数加载依赖模块 require(moduleID)

    define(function(require) {
      var a = require('./a');
      a.doSomething();
    });
    

    它接受 模块标识 作为唯一参数。

    请牢记,为了使静态分析能成功获取到模块依赖信息,在书写模块时,需要遵循一些简单的 规则

    require.async

    该方法可用来异步加载模块,并在加载完成后执行回调函数。

    define(function(require, exports, module) {
      // 加载一个模块
      require.async('./b', function(b) {
        b.doSomething();
      });
      
      // 加载多个模块
      require.async(['./c', './d'], function(c, d) {
        // do something
      });
    });
    

    require.resolve

    使用 require() 的内部机制来解析并返回模块路径。该函数不会加载模块,只返回解析后的路径。

    require.load

    该方法可用来异步加载脚本,并在加载完成后,执行指定的回调函数。开发插件时, 可以通过覆盖该方法来实现自定义的资源加载。

    require.constructor

    有时候,我们需要给所有 require 参数对象添加一些公用属性或方法。这时, 使用 require.constructor 来实现会非常方便。

    module

    module 参数存储模块的元信息。拥有以下成员:

    module.id

    当前模块的唯一标识。 require(module.id) 必然返回此模块的 exports

    define(function(require, exports, module) {
      console.log(module.id); // http://path/to/this/file.js
      console.log(require(module.id) === exports); // true
    });
    

    module.dependencies

    module.dependencies 是一个数组,表示当前模块的依赖列表。

    该数组只读:模块加载完成后,修改该数组不会有任何效果。

    module.exports

    exports 对象由模块系统创建,这不能满足开发者的所有需求, 有时候会希望 exports 是某个类的实例。 这时可用 module.exports 来实现:

    define(function(require, exports, module) {
      console.log(module.exports === exports); // true
      module.exports = new SomeClass();
      console.log(module.exports === exports); // false
    });
    

    注意,对 module.exports 的赋值需要同步执行,它不能放在回调函数里。 下面这样是不行的:

    x.js:

    define(function(require, exports, module) {
      setTimeout(function() {
        module.exports = { a: "hello" };
      }, 0);
    });
    

    y.js:

    define(function(require, exports, module) {
      var x = require('./x');
      console.log(x.a); // undefined
    });
    

    module.constructor

    时候,我们需要给所有 module 参数对象添加一些公用属性或方法。在这种情况下, 使用 module.constructor 可以很好地满足需求。

    extend.js:

    define(function(require, exports, module) {
      var Module = module.constructor;
    
      Module.prototype.filename = function() {
        var id = this.id;
        var parts = id.split('/');
        return parts[parts.length - 1];
      };
    });
    

    a.js:

    define(function(require, exports, module) {
      exports.filename = module.filename();
    });


    --------------------------------------------------------------------------------
    SeaJS提供了模块化的能力,前面我们已经看到了SeaJS定义模块、引用模块的方法,而这里就要用到SeaJS加载并启动模块的两种方式
    a、使用data-main
    为<script src="assets/scripts/seajs/sea.js" id="seajsnode"></script>添加data-main="application/application"属性即可:
    <script src="assets/scripts/seajs/sea.js" id="seajsnode" data-main="application/application"></script>  
    //~~~~ seajs.version == 2.0 data-main可用 seajs.version=2.2.x data-main方式加载入口模块不可用; 类似requirejs的 data-main
    SeaJS会根据data-main指定的模块来作为整个应用的入口模块。SeaJS找到这个模块之后,就会加载执行这个模块对应的文件。
    那么,SeaJS又是怎么找到这个文件呢?也就是说,这个模块对应的加载路径是多少?
    “算法”是:SeaJS_URL_base + data-main
    如上文,该例子的SeaJS_URL_base是HelloSeaJS/assets/scripts/

    那么,加载路径就是HelloSeaJS/assets/scripts/application/application.js(SeaJS会自动加上.js后缀)

    b、使用seajs.use
    在<script src="assets/scripts/seajs/sea.js" id="seajsnode">后面加上:
    <script> seajs.use("application/application"); </script>
    其实这两种效果在这个例子中是一样的,data-main通常用在只有一个入口的情况,use可以用在多个入口的情况,具体用法,看这里:https://github.com/seajs/seajs/issues/260

    如果你对你的程序有完全的控制权,建议使用data-main的方式,这样整个页面就只有一段script标签!作为一名前端开发人员,我不得不惊叹:干净、完美!

    嗯,SeaJS已经替我们想到了这个问题,于是我们就采用SeaJS提供的方式来合并压缩吧(当然你也可以自己用别的方式压缩)。

    SeaJS在2.0之前,是采用SPM作为压缩合并工具的,到了2.0,改为Grunt.js,SPM变为包管理工具,类似NPM(不知道NPM?Google一下吧)

    自动化不仅是科技带给社会的便利,也是Grunt带给前端的瑞士军刀。使用Grunt,可以很方便的定制各种任务,如压缩、合并等。使用Grunt之前,需要安装node环境和grunt工具,Google一下,十分钟后回来。

    ……

    Grunt最核心的就两个部分,package.json、Gruntfile.js。

  • 相关阅读:
    H5性能优化
    【JavaScript 】for 循环进化史
    (四十四)通过系统Gallery获取图片
    (四十三)获取图片exif信息
    (四十二)、加载大分辨率图片到内存
    (九)JAVA设计模式之单例模式
    (四十一)Activity切换动画
    (四十)android在代码中,如何设置自定义对话框在屏幕中的位置和大小
    (三十九)android动画 Animation四大属性 详解(转载:http://www.android100.org/html/201304/25/2295.html)
    (三十八)android:windowSoftInputMode属性详解
  • 原文地址:https://www.cnblogs.com/stephenykk/p/3680127.html
Copyright © 2020-2023  润新知