zoukankan      html  css  js  c++  java
  • Sea.js 学习笔记

    Sea.js 追求简单、自然的代码书写和组织方式,具有以下核心特性:
    • 简单友好的模块定义规范:Sea.js 遵循 CMD 规范,可以像 Node.js 一般书写模块代码。
    • 自然直观的代码组织方式:依赖的自动加载、配置的简洁清晰,可以让我们更多地享受编码的乐趣。

    Sea.js 还提供常用插件,非常有助于开发调试和性能优化,并具有丰富的可扩展接口。



        一、引入sea.js

        在调用 seajs.use 之前,需要先引入 sea.js 文件,推荐直接使用 script 标签同步引入:

    <script src="path/to/sea.js"></script>
        (使用直接引入外部脚本的方式的话,config内base路径则为该script的src属性的绝对路径)

        为了满足某些场景下的性能优化需求,也可以将 sea.js 的源码内嵌:

    <script> // sea.js 的源码 </script>

        (注意:代码内嵌时,需要通过 seajs.config 手动配置 base 路径。)

       

        二、seajs配置说明:

        seajs.config : (可进行配置seajs的路径寻找规则、模块别名映射、预加载模块、以及seajs的基础路径)

        seajs.config支持的属性有:

        'alias' : (当模块标识很长时,可以使用 alias 来简化,使用 alias,可以让文件的真实路径与调用标识分开,有利于统一维护。)

        'paths' : (当目录比较深,或需要跨目录调用模块时,可以使用 paths 来简化书写,paths 配置也可以结合 alias 配置一起使用,让模块引用非常方便。)

        'vars' : (有些场景下,模块路径在运行时才能确定,这时可以使用 vars 变量来配置,vars 配置的是模块标识中的变量值,在模块标识中用 {key} 来表示变量。)

        'map' : (该配置可对模块路径进行映射修改,可用于路径转换、在线调试等。)

        'preload' : (使用 preload 配置项,可以在普通模块加载前,提前加载并初始化好指定模块。preload 中的空字符串会被忽略掉。)

        'debug' : (值为 true 时,加载器不会删除动态插入的 script 标签。插件也可以根据 debug 配置,来决策 log 等信息的输出。)

        'base' : (Sea.js 在解析模块路径标识时,会基于 base 路径来解析。)

        'charset' : (获取模块文件时,<script><link> 标签的 charset 属性。 默认是 utf-8)


        使用案例:
        1. alias :模块别名配置
    seajs.config({
            'alias' : {
                'jquery': 'jquery/jquery/1.10.1/jquery',
                'app/biz': 'http://path/to/app/biz.js'
            }
        });
        define(function(require, exports, module) {
           var $ = require('jquery');
           //=> 加载的是 http://path/to/base/jquery/jquery/1.10.1/jquery.js
    
           var biz = require('app/biz');
           //=> 加载的是 http://path/to/app/biz.js
        });
     
       2.vars 配置的是模块标识中的变量值,在模块标识中用 {key} 来表示变量。
    seajs.config({
          vars: {
            'locale': 'zh-cn'
          }
        });
        define(function(require, exports, module) {
             var lang = require('./i18n/{locale}.js');
             //=> 加载的是 path/to/i18n/zh-cn.js
        });
     
       3.该配置可对模块路径进行映射修改,可用于路径转换、在线调试等。
    seajs.config({
          map: [
            [ '.js', '-debug.js' ]
          ]
        });
        define(function(require, exports, module) {
             var a = require('./a');
             //=> 加载的是 path/to/a-debug.js
        });

        4.使用 preload 配置项,可以在普通模块加载前,提前加载并初始化好指定模块。
    // 在老浏览器中,提前加载好 ES5 和 json 模块, (注:preload 中的空字符串会被忽略掉。)  
    seajs.config({ preload: [ Function.prototype.bind
    ? '' : 'es5-safe', this.JSON ? '' : 'json' ] }); // (注意:preload 中的配置,需要等到 use 时才加载。比如:) seajs.config({ preload: 'a' }); // 在加载 b 之前,会确保模块 a 已经加载并执行好 seajs.use('./b'); // preload 配置不能放在模块文件里面: seajs.config({ preload: 'a' }); define(function(require, exports) { // 此处执行时,不能保证模块 a 已经加载并执行好,只有在调用 use或require.async时,preload里面预先标识的模块才会被加载。 });

        5. 配置seajs寻找模块时的相对基础路径
    seajs.config({
            'base' : '../sea-modules/'
        });
    /*
        这里需要注意的是在设置base属性的时候,./ 或 ../ 相关路径是根据当前html文件路径走的,如果html路径为:/var/www/html/index/
        那么上面的代码设置的base路径就是:/var/www/html/sea-modules/,
        如果不手动设置该项base属性的话,sea.js会进行正则匹配然后获得sea.js的目录路径,具体正则匹配和设置可查看源码。
    */

        以上是seajs.config 的常用配置项。
     

        三、seajs引入模块有两种方法:

        1.seajs.use    : public API,    可在全局任何位置调用该方法(前提是保证seajs对象未被覆盖方法未被重写)

        2.seajs.async  : private API,   在执行全局函数define时,通常会传递一个函数进去当factory参数,然后seajs在执行该函数时,会传递三个参数:

        require(type:[Function];desc:[一个封装在内部的加载文件模块类]),

        exports(type[Object];desc:[该模块的一个属性]),

        module(type[Object];desc:[该模块自身的引用])

        第一种情况:seajs.use('abc');

        第二种情况:seajs.use(['a', 'b']);

        两种加载格式,但这里大家需要注意的是,Sea.js中加载一个文件就等于创建一个Module实例,每个实例都有以下属性

        this.uri = uri 
        this.dependencies = deps || []    // 依赖自身的模块ID
        this.exports = null   
        this.status = 0        // 当前模块的状态(FETCHING: 1,SAVED: 2,LOADING: 3,LOADED: 4,EXECUTING: 5,EXECUTED: 6)
        this._waitings = {}    // 哪些模块依赖我?
        this._remain = 0       // 卸载依赖项的数量

        然后这个模块都被存储在一个叫 cachedMods 的Object当中,然后模块的uri就是键 模块自身实例就是值。

        比如第一种调用use情况的话,最终结果: cachedMods里的键为(seajs模块自生成的一个标识ID) 对应值为 Module实例; use函数第一个参数'abc'不是Module模块的标识id, 而是该模块的一个依赖, 最终这个依赖‘abc’会通过一系列函数提取出绝对路径 同样会被require方法生成(js|css)元素添加到DOM树当中。

        四、模块标识

        模块标识是一个字符串,用来标识模块。在 requirerequire.async 等加载函数中,第一个参数都是模块标识。

    Sea.js 中的模块标识是 CommonJS 模块标识 的超集:

    1. 一个模块标识由斜线(/)分隔的多项组成。
    2. 每一项必须是小驼峰字符串、 ...
    3. 模块标识可以不包含文件后缀名,比如 .js
    4. 模块标识可以是 相对顶级 标识。如果第一项是 ...,则该模块标识是相对标识。
    5. 顶级标识根据模块系统的基础路径来解析。
    6. 相对标识相对 require 所在模块的路径来解析。

          注意: 符合上述规范的标识肯定是 Sea.js 的模块标识,但 Sea.js 能识别的模块标识不需要完全符合以上规范。 比如,除了大小写字母组成的小驼峰字符串,Sea.js 的模块标识字符串还可以包含下划线(_)和连字符(-), 甚至可以是 http://https://file:/// 等协议开头的绝对路径。


        1.相对标识
        相对标识以 . 开头,只出现在模块环境中(define 的 factory 方法里面)。相对标识永远相对当前模块的 URI 来解析:
       // 在 http://example.com/js/a.js 的 factory 中:
        require.resolve('./b');
        // => http://example.com/js/b.js
    
        // 在 http://example.com/js/a.js 的 factory 中:
        require.resolve('../c');
        // => http://example.com/c.js

      2.顶级标识
       顶级标识不以点(.)或斜线(/)开始, 会相对模块系统的基础路径(即 Sea.js 的 base 路径)来解析:

    // 假设 base 路径是:http://example.com/assets/
    
    // 在模块代码里:
    require.resolve('gallery/jquery/1.9.1/jquery');
    // => http://example.com/assets/gallery/jquery/1.9.1/jquery.js

      模块系统的基础路径即 base 的默认值,与 sea.js 的访问路径相关:

      如果 sea.js 的访问路径是: http://example.com/assets/sea.js

      则 base 路径为: http://example.com/assets/

      当 sea.js 的访问路径中含有版本号时,base 不会包含 seajs/x.y.z 字串。 当 sea.js 有多个版本时,这样会很方便。

      如果 sea.js 的路径是: http://example.com/assets/seajs/1.0.0/sea.js

      则 base 路径是:  http://example.com/assets/

      当然,也可以手工配置 base 路径:

    seajs.config({ base: 'http://code.jquery.com/' }); // 在模块代码里: require.resolve('jquery'); // => http://code.jquery.com/jquery.js 

      3.普通路径:
      除了相对和顶级标识之外的标识都是普通路径。普通路径的解析规则,和 HTML 代码中的 <script src="..."></script> 一样,会相对当前页面解析。

    // 假设当前页面是 http://example.com/path/to/page/index.html
    
    // 绝对路径是普通路径:
    require.resolve('http://cdn.com/js/a');
    // => http://cdn.com/js/a.js
    
    // 根路径是普通路径:
    require.resolve('/js/b');
    // => http://example.com/js/b.js
    
    // use 中的相对路径始终是普通路径:
    seajs.use('./c');
    // => 加载的是 http://example.com/path/to/page/c.js
    
    seajs.use('../d');
    // => 加载的是 http://example.com/path/to/d.js

      提示:
        1.顶级标识始终相对 base 基础路径解析。
        2.绝对路径和根路径始终相对当前页面解析。
        3.require 和 require.async 中的相对路径相对当前模块路径来解析。
        4.seajs.use 中的相对路径始终相对当前页面来解析。

     四、文件后缀的自动添加规则

      Sea.js 在解析模块标识时, 除非在路径中有问号(?)或最后一个字符是井号(#),否则都会自动添加 JS 扩展名(.js)。如果不想自动添加扩展名,可以在路径末尾加上井号(#)。

    // ".js" 后缀可以省略:
    require.resolve('http://example.com/js/a');
    require.resolve('http://example.com/js/a.js');
      // => http://example.com/js/a.js
    
    // ".css" 后缀不可省略:
    require.resolve('http://example.com/css/a.css');
      // => http://example.com/css/a.css
    
    // 当路径中有问号("?")时,不会自动添加后缀:
    require.resolve('http://example.com/js/a.json?callback=define');
      // => http://example.com/js/a.json?callback=define
    
    // 当路径以井号("#")结尾时,不会自动添加后缀,且在解析时,会自动去掉井号:
    require.resolve('http://example.com/js/a.json#');
      // => http://example.com/js/a.json

      内容没有补全以及描述比较差劲,后续还会补充和更正完善,并当有时间的时候将seajs源码进行小小的解读。

       author: 羽翼飞扬




       
  • 相关阅读:
    聊聊高并发(二十)解析java.util.concurrent各个组件(二) 12个原子变量相关类
    windows curl ssl版本号编译
    扩展MSEG 加入Z字段
    HDU 1565 1569 方格取数(最大点权独立集)
    Codeforces Round #277.5 (Div. 2)
    葡萄城公布新版ActiveReports 9报表控件和报表server
    we标签
    ADO.NET (二)—— ADO和ADO .NET对照
    补:小玩文件2--将文本文件里的全部行加上行号后写到新文件里
    poj3061 Subsequence ,尺取法
  • 原文地址:https://www.cnblogs.com/yuyifeiyang/p/3549791.html
Copyright © 2011-2022 走看看