zoukankan      html  css  js  c++  java
  • 前端框架 seajs 使用总结

    CMD 模块定义规范

    • seajs中,所有的javascript都遵循CMD模块定义规范。该规范明确定义了模块的定义格式和模块依赖的规则说明。
    • define.cmd : 一个空对象,可以用来判断当前页面是否存在cmd模块加载器,调用方法如下:
    if(typeof define.cmd ==="undefined" || define.cmd){
        //Seajs存在cmd模块加载器
    }
    • 与 RequireJS 的 AMD 规范相比,CMD 规范尽量保持简单,并与 CommonJS 和 Node.js 的 Modules 规范保持了很大的兼容性

    seajs的特点


    • 简单友好的模块定义规范:遵循CMD规范。
    • 简单直观的代码组织方式:依赖自动加载,配置简洁清晰。

    seajs的兼容性


    Chrome 3+ ✔ Firefox 2+ ✔ Safari 3.2+ ✔ Opera 10+ ✔ IE 5.5+ ✔
    
    理论上适用于任何浏览器,包括 Mobile 。
     
     

    seajs的配置

    seajs.config({
        // 别名配置
        alias: {
            'es5-safe': 'gallery/es5-safe/0.9.3/es5-safe',
            'json': 'gallery/json/1.0.2/json',
            'jquery': 'jquery/jquery/1.10.1/jquery'
        },
        // 路径配置
        paths: {
            'gallery': 'https://a.alipayobjects.com/gallery'
        },
        // 变量配置
        vars: {
            'locale': 'zh-cn'
        },
        // 映射配置
        map: [
            ['http://example.com/js/app/', 'http://localhost/js/app/']
        ],
        // 预加载项
        preload: [
            Function.prototype.bind ? '' : 'es5-safe',
            this.JSON ? '' : 'json'
        ],
        // 调试模式
        debug: true,
        // Sea.js 的基础路径
        base: 'http://example.com/path/to/base/',
        // 文件编码
        charset: 'utf-8'
    });
     
     
     
     

    alias Object

    可以简化较长模块标示的书写。
    seajs.config({
       // 别名配置
        alias: {
            'es5-safe': 'gallery/es5-safe/0.9.3/es5-safe',
            'json': 'gallery/json/1.0.2/json',
            'jquery': 'jquery/jquery/1.10.1/jquery'
        }
    });
    模块定义:
    define(function(require, exports , module){
        var $ = require("jquery");
        //==>加载的是http://example.com/path/to/base/jquery/jquery/1.10.1/jquery.js
    });
     

    path Object

    如果依赖层次较深,或者跨目录调用模块,path可以简化书写。
    path 可以结合alias一起使用。
    seajs.config({
        // 路径配置
        paths: {
            'gallery': 'https://a.alipayobjects.com/gallery'
        },
    });
    模块定义:
    define(function(require,exports, module){
        var json = require("gallery/jsonparser");
        //==> 加载的是https://a.alipayobjects.com/gallery/jsonparser.js
    });
     
    vars Object
    有些模块需要在运行时才能确定,可以使用vars指定。
    vars 配置的是模块标识中的变量值,在模块标识中用 {key} 来表示变量。
     
    seajs.config({
    // 变量配置
        vars: {
            'local': 'zh-cn'
        },
    });
    模块定义
    define(function(require, exports, module){
        var language_config = require("language/{local}.js");
        console.log(language_config);//获取中文配置文件
    });
     
    map Array
    路由模块路径。
    seajs.config({
        // 映射配置
        map: [
            ['http://example.com/js/app/', 'http://localhost/js/app/'],
            ['.js','-debg.js']
        ],
    });
     
    define(function(require, exports, module){
        var m_a = require("./a");
        //==>加载的是./a-debug.js
    });
     

    preLoad Array

    预加载一些公共模块或者指定模块
    seajs.config({
        // 预加载项
        preload: [
            Function.prototype.bind ? '' : 'es5-safe',
            this.JSON ? '' : 'json'
        ],
    });
    preLoad中的配置,需要等到use时才加载
    seajs.use("./b",function(){
        //在加载b模块之前,预加载项已经加载完成。
    });
    preLoad中的配置,无法保证模块定义中已经加载完成并执行完成。
     

    debug String

    值为 true 时,加载器不会删除动态插入的 script 标签。插件也可以根据 debug 配置,来决策 log 等信息的输出。
     
    base String
    Sea.js 在解析顶级标识时,会相对 base 路径来解析。
     
    charset String | Function
    获取模块文件时,<script> 或 <link> 标签的 charset 属性。 默认是 utf-8
    charset还可以是函数:
    seajs.config({
        charset: function(url) {
            // xxx 目录下的文件用 gbk 编码加载
            if (url.indexOf('http://example.com/js/xxx') === 0) {
                return 'gbk';
            }
            // 其他文件用 utf-8 编码
            return 'utf-8';
        }
    });
     
    注意:seajs.config 可以多次执行,每次执行都会对配置项进行合并操作。
    config 会自动合并不存在的项,对存在的项则进行覆盖。
     

    建议seajs.config所在的js文件 

    独立成一个文件时,一般通过 script 标签在页面中同步引入。
     
    模块定义(define Function)
     
    定义函数:
    函数: define(factory)
    其中,define方法是全局方法,作用域是window;factory可以是字符串,对象或者函数。
     
     
    Factory类型:
     
    • 字符串或者对象。
       define({"username":"fol","age":"23"});    //factory是对象类型
        define("I love zhuzhou");    //factory是字符串类型
     
        如果模块的factory类型是字符串或者对象,那么该模块对外提供的接口(输出)就是字符串或者对象本身。
    • 函数
            定义格式1:
            define(function(require, exports, module){
            //todo
       });
     
          如果factory的类型是函数,那么给函数就是该模块的构造函数,执行该函数可以得到模块对外提供接口。
          factory默认传入的参数是require, exports, module。
          这种模块定义方式未指定模块id,模块依赖列表。
        
          定义格式2:
          define(id? , deps?, factory?)
          模块定义也可以接受两个以上参数,其中id定义模块的id,deps声明模块依赖的其他模块列表(Array)。
           define("user", ["jquery", "ajax", "upload", "json"], function(require, exports, module){
           // todo 
       });
     
        注意:id 和 deps参数是可选参数,可以通过构建工具自动生成。
        
     
    模块引用(require Function)
     
     
    模块加载函数:
     
    函数: require( id? )
    其中,require对象是factory的第一个参数,同样,require函数也是全局函数,作用域是window;
    id是模块标识,一般在模块定义函数中被调用,用来获取其他模块提供的接口。
    define(function( require, exports, module ) {
        var $ = require("jquery");  //引入jquery模块
        $(document).ready(function(){
            $("#bt").on("click", function(){
                  console.log("the bt is clicked");
            });
        });
    });
     
    异步加载:
     
    函数: require.async( id?, callback? )
    其中,id是模块的标识,callback是模块异步加载完成后的回调函数。
     
    define(function(require, exports, module){
        //异步加载单个模块
        require.async("plugins/bootstrap", function(b){
            b.doSomething();
        });
        //异步加载多个模块
        require.async(["./utils/datepicker","./utils/colorpicker"], function(datepicker, colorpicker){
            datepicker.init();
            colorpicker.init();
        });
    });
    注意:require()是同步执行的,require.async()是异步回调执行,require.async用来执行可以延迟加载执行的模块。
     
     
     
    路径解析:
    函数: require.resolve(id?)
    其中,id 是模块的唯一标识,只用来解析模块的绝对路径。
    define(function(require, exports, module){
        val jqueryPath = require.resolve("jquery");    //解析jquery的绝对路径    
        //http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.js
    });
     
    seajs 三个对象
     
    exports Object
    exports 是一个对象,负责对外提供模块接口。
    define(function(require, exports, module){
          function trim() {
                return this.replace(/(^s*)|(s*$)/g, "")
          }
          exports.trim = trim;    //把内部函数暴露给其他模块
          exports.config = {"username":"foo", "age":"23"};//把内部对象暴露给其他模块
    });
     
    除了使用exports 对象对外提供接口外,还可以使用return直接对外提供接口
    define(function(require, exports, module){
          function trim() {
                return this.replace(/(^s*)|(s*$)/g, "")
          }
          return {
            "trim":trim,
            "config":{"username":"foo", "age":23}
          }
    });
    如果模块中return语句是唯一的代码,那么可以使用define({})简化模块定义:
    define({
       "trim":function(){
             
    return this.replace(/(^s*)|(s*$)/g, "")
        },
        "config":{"username":"foo","age":23}
    );
    上面的格式可以适合定义JSONP模块。
    注意:不能对exports重新赋值,这样虽然不会影响到module.exports 。但是无法对外提供接口,可以赋值module.exports达到对外提供接口的目的。
    define(function(require, exports , module){
        module.exports = {
            trim:function(){ return this.replace(/(^s*)|(s*$)/g, "");},
            config:{"username":"foo", "age":23}
        }
    });
     
    module Object
    module是一个对象,其中存储着于当前模块相关的一些方法和属性。
    module.id:返回模块的标识
    module.uri:返回模块的绝对路径。
    define(function(require, exports, module){
        var module_uri = module.uri;
        //==> 
    http://example.com/path/to/this/file.js
    });
    一般情况下,如果没有定义模块id, 那么module.id == module.uri,两者完全相同。
     
     
    module.dependencies Array :返回当前模块依赖的模块列表。
    module.exports :返回当前模块对外提供的接口对象。
    注意:传递给factory方法的参数中exports 只是module.exports 的一个引用,只能通过exports来对外提供接口,但是module.exports可以是一个类的实例。
    而且,对module.exports 赋值不能通过回调函数等方法异步执行,只能同步执行。
    define(function(require, exports, module) {
      // exports 是 module.exports 的一个引用
      console.log(module.exports === exports); // true
    
      // 重新给 module.exports 赋值
      module.exports = new SomeClass();
    
      // exports 不再等于 module.exports
      console.log(module.exports === exports); // false
      //module.exports 不能异步执行
      setTimeout(function(){
        module.exports = {"username":"foo", "age":23};    //错误,无法对外提供接口
      }, 1000);
    
    });
    
    
    seajs.use Function 
    函数:seajs.use(ids?, callback?)
    作用:用在页面上加载其他模块。
     
    //加载一个模块
    seajs.use("./a");
     
    //加载一个模块并回调
    seajs.use("./a", function(a){
        a.doSomething();
    });
     
    //加载多个模块并回调
    seajs.use(["jquery","./a"], function($, a){
        $("#bt").click(function(){
            //doSomething
        });
        a.doSomething();
    });
    注意:seajs.use方法和document.ready()方法没有必然关系,如果某些操作需要在document ready后才能执行操作,需要借助jquery等依赖模块。
     
     

    seajs.cache Function

    函数:seajs.cache();
    可以用来查看当前页面加载的依赖模块列表。
     
    seajs.resolve Function
    函数:seajs.resolve(id?);
    可以用来获取依赖模块的绝对路径。
     
     

    seajs.data Function

    函数:seajs.data();
    可以用来seajs的所有配置以及一些内部变量,可以用在插件开发中。
     
     

    模块标识与路径关系

    模块标识:
    模块标识主要以小驼峰,. 或者 .. 为主。
     
    //在http://example.com/my/js/user.js中
    define(function(require, exports, module){
        var path = require.resolve("./json");
        //==>路径为http://example.com/my/js/json.js
        
        var path2 = require.resolve("../json");
        //==> 路径为http://example.com/my/json.js
    });
    注意:以小驼峰开头的模块标识是顶级标识,以base为根目录加载模块文件;以.和..开头的模块标识是相对标识,以当前模块文件所在的位置为基础根目录加载。
     
    //假设base 是http://examle.com/my/js
    define(function(require, exports, module){
        var path = require.resolve("json");
        //==>路径为http://example.com/my/js/json.js
    });
     
     
    注意:页面中基于当前页面为根目录加载模块文件。
     
     

    构建工具那些事

    构建过程描述:
    • 提取操作
    提取模块的标识id以及模块的其他依赖dependencies。
     
    //a.js
    define(function(require, exports, module){
        var b = require("./b");
    });
     
    经过提取操作,a.js文件会变成临时文件:
     
    define("xxx/1.0.0/a",["./b"],function(require, exports, module){
        var b = require("./b");
    });
    • 压缩操作
    经过上面的提取操作后,构建工具就可以调用任何 JS 压缩工具来进行压缩了,require 参数也可以被压缩成任意字符。相比于其他的压缩工具,CMD模块的构建过程增加了id和dependencies的提取过程。
     
    为什么要提取模块标识Id:
     
    我们在模块定义过程中,可能会合并两个模块定义文件,使得模块管理更加方便和易用。
    //a.js
    define(function(require, exports, module){
        //todoSomething
    });
     
    //b.js
    define(function(require, exports, module){
        //todoSomething
    });
     
    如果我们希望合并以上两个文件,那么会出现模块定义不清楚,无法确认加载哪个模块的问题,所以在模块构建过程中需要提取模块标识id。
     

    此外,即便不合并,保持一个文件一个模块,如果压缩时不提取 id,那么在 IE6-9 下也有可能会出现问题。

     
    为什么要提取模块依赖dependencies:
     
    为了保证压缩文件随意压缩代码,构建工具在提取id的同时,也会提取dependencies数组。这样seajs不会再通过factory.toString()借助于正则匹配来获取依赖,直接可以通过factory函数的第二个参数拿到依赖数组。
    注意:一旦factory的第二个参数定义了依赖数组,那么seajs将不会使用正则匹配的方式去分析并获取依赖,而是直接使用factory第二个参数提供的依赖数组作为所有的依赖。
  • 相关阅读:
    CSP-S 2019游记
    南校五天集训游记
    web.xml模板
    JDBC Template的基本使用
    Spring AOP(3)使用AspectJ xml配置
    Spring AOP(2)使用AspectJ注解
    Spring Aop(面向切面编程)
    Spring Bean管理3(xml与注解混合使用)
    Python核心技术与实战——十二|Python的比较与拷贝
    test
  • 原文地址:https://www.cnblogs.com/amylis_chen/p/14140345.html
Copyright © 2011-2022 走看看