Hliang

个人站

我说晚了你就不学了吗?


cmd规范与sea.js

cmd规范:

  • 特性:
    • 一个模块就是一个单独的文件
    • 由于每个模块都是属于define关键字函数的回调函数被调用,每个模块都是一个单独的作用域
    • 预加载、懒执行(预加载就是预先把所有的模块全部加载完,懒执行就是需要执行哪块才执行哪块)
  • 关键字
    • define 定义一个模块
    • require 加载一个模块
    • exports 暴露一个模块
    • module 模块

模块系统主要解决模块的定义、依赖和导出

伪代码如下:

替换成真正的代码:

sea.js

sea.js在互联网公司里面主要是一些现有的项目还在使用,但是从学习的角度上来说,还是可以学习的,可以让我们知道一个模块化的标准库主要有哪些API,另外我们的node.js的模块化方面的API和sea.js也是很像的。

官网地址

  • 用npm安装:npm install seajs --save

  • 文件夹名称含义

    • dist 我们要引用的sea.js库的文件夹,其中sea.js是压缩过的,类似jquery.min.js,还有一个sea-debug.js,类似没压缩过的jQuery,方便我们debug调试的
    • docs 文档
    • lib 这是写了一个兼容node.js的版本,不用管
    • src sea.js的源代码
    • tests 测试文件

书写sea.js代码的步骤

  • html文件中引入sea.js库
  • 使用seajs.use加载主模块(也叫入口模块),起名一般叫main.js
  • 模块的定义方法
    • 在我们的sea.js当中一个模块就是一个文件
    • 调用define函数定义主模块
    • 用require函数加载其他第三方模块
    • 用module.exports或exports来暴露当前模块的东西
  • 注意点
    • define(function(require,exports,module){});这里面的require,exports,module三个参数的名字是固定写法,不能简写,顺序不能错了 记忆方法:rem –> 依赖注入
    • 如果define里的参数想省略,只能从后面开始省略,只要写了后面的,前面的必须要写上 –> 推荐写全,不要省
    • 如果一个模块既不需要公开成员变量,也不需要依赖第三方模块,那么可以全部省略
    • seajs.use(“入口模块”)可以加回调函数,形式如:seajs.use(“入口模块”,callback);

seajs的路径问题

  • 在sea.js当中,js/main和./js/main的含义不是一样的
    • js/main代表的是在sea.js所在的文件为基准去找,所以找到的是 –> seajs库所在的父级文件夹/js/main.js 这样的话会找不到的
    • ./js/main代表的是以当前html文件去找
    • seajs.use(),require(“xxx”) –> 其实这里的xxx叫模块标识,不是路径
  • config的作用就是为了简化调用模块
    • base 设置路径
    • alias 设置模块的别名,简化调用

  • 默认的base值是seajs库文件所在的父文件夹

  • 注意:如果没有特殊说明,任何时候尽量用相对路径。

seajs如何把非cmd模块转换成cmd模块

不管是jQuery还是zepto,如果你想把它们改造成一个符合cmd规范的模块,必须加上一段类似上面的代码。

sea.js之module.exports与exports辨析

  • 本质上用的还是module.exports这个对象,exports的值是module.exports 的引用地址,通过这种方式,我们可以少写一个”module.”
    define(function(require,exports,module){
          console.log(exports === module.exports);    //true
    })
  • module.exports 指向新的对象时,exports 将会断开了与 module.exports 的引用

如何理解预加载、懒执行

预加载就是预先把所有的模块全部加载完,懒执行就是需要执行哪块才执行哪块

加载流程理解

  • html文件加载主模块
  • 主模块加载依赖的第三方模块
  • 第三方模块如果还有其他的第三方模块依赖,则进一步加载其他第三方模块

sea.js模块加载原理分析

sea.js的require,use方法之所以能够加载js文件,本质上都是利用给script标签一个src属性地址,并且嵌入追加到DOM树中的时候,会自动去下载这个js文件并且会执行

function loadJs(path,callback){
  var oHead = document.getElementsByTagName("head")[0];
  var oNode = document.createElement("script");
  var isSupportOnload = "onload" in oNode;
  if(isSupportOnload){
    oNode.onload = function(){
      if(callback && typeof callback === 'function'){
        callback();
      }
    }
  }else{
    oNode.onreadystatechange = function(){
      if(oNode.readyState === 'loaded' || oNode.readyState === 'complete' && callback && typeof callback === 'function'){
        callback();
      }
    }
  }
  oNode.setAttribute("type","text/javascript");
  var reg = /\.js$/;
  if(!reg.test(path)){
    path += ".js";
  }
  oNode.setAttribute("src",path);
  oHead.appendChild(oNode);
}