SeaJS 是一个模块加载器,模块加载器需要实现两个基本功能:

  • 实现模块定义规范,这是模块系统的基础。
  • 模块系统的启动与运行。

define参数

在 CMD 规范中,一个模块就是一个文件。代码的书写格式如下:

define(factory)

  • factory 为对象、字符串时,表示模块的接口就是该对象、字符串。
  • factory 为函数时,表示是模块的构造方法。执行该构造方法,可以得到模块向外提供的接口。factory默认会传入三个参数:require、exports 和 module。

  // factory 为对象

  define({ "foo": "bar" });
 
  // factory 为函数
  define(function(require, exports, module) {
    // 模块代码
  });

factory参数

factory参数的使用如下:

// 所有模块都通过 define 来定义
define(function(require, exports, module) {
  // 通过 require 引入依赖,获取模块 a 的接口
  var a = require('./a');
 
  // 调用模块 a 的方法
  a.doSomething();
 
  // 通过 exports 对外提供接口foo 属性
  exports.foo = 'bar';
 
  // 对外提供 doSomething 方法
  exports.doSomething = function() {};
 
  // 错误用法!!!
  exports = {
    foo: 'bar',
    doSomething: function() {}
  };
 
  // 正确写法,通过module.exports提供整个接口
  module.exports = {
    foo: 'bar',
    doSomething: function() {}
  };
});
 

require:Function

  • require是一个函数方法,用来获取其他模块提供的接口,而且是同步往下执行。require的模块不能被返回时,应该返回null。

  • require.async(id, callback?):用来在模块内部异步加载模块,并在加载完成后执行指定回调。require的模块不能被返回时,callback应该返回null。callback接受返回的模块作为它的参数。

  • require.resolve(id):不会加载模块,只返回解析后的绝对路径

为什么那么死规定?!
首先你要知道SeaJS 是如何知道一个模块的具体依赖的。SeaJS 通过 factory.toString() 拿到源码,再通过正则匹配 require 的方式来得到依赖信息。这也是必须遵守 require 书写约定的原因。

exports:Object

用来在模块内部对外提供接口。
exports 仅仅是 module.exports 的一个引用。在 factory 内部给 exports 重新赋值时,并不会改变 module.exports 的值。因此给 exports 赋值是无效的,不能用来更改模块接口。

module:Object

  • module.uri:解析后的绝对路径
  • module.dependencies:模块依赖
  • module.exports:暴露模块接口数据,也可以通过 return 直接提供接口,因个人习惯使用。
  • 对 module.exports 的赋值需要同步执行,慎重放在回调函数里,因为无法立刻得到模块接口数据。

三种类型的标识:

  • 相对标识:以 . 开头(包括.和..),相对标识永远相对当前模块的 URI 来解析。
  • 顶级标识:不以点(.)或斜线(/)开始, 会相对模块系统的基础路径(即 SeaJS配置 的 base 路径)来解析。

  seajs.config({

    base: 'http://code.jquery.com/'

  });

  // 在模块代码里:

  require.resolve('jquery');

  // 解析为 http://code.jquery.com/jquery.js

  • 普通路径:除了相对和顶级标识之外的标识都是普通路径,相对当前页面解析。绝对路径和根路径也是普通路径。绝对路径比较容易理解。根路径是以“/”开头的,取当前页面的域名+根路径,

     如下所示:

// 假设当前页面是 http://example.com/path/to/page/index.html
require.resolve('/js/b');
// 解析为 http://example.com/js/b.js
 
如上所示,/js/b可省略后缀.js,但是”.css” 后缀不可省略。
SeaJS 在解析模块标识时,除非在路径中有问号(?)或最后一个字符是井号(#),否则都会自动添加 JS 扩展名(.js)。
 

模块系统的启动与运行

直接使用 script 标签同步引入sea.js文件后,就可以使用seajs.use(id, callback?)在页面中加载模块了!

通过define定义许多模块后,得让它们能跑起来,如下:

<script type="text/javascript" src="../gb/sea.js"></script>
<script>
  seajs.use('./index.js');
</script>
 

最佳实践:

  • seajs.use 理论上只用于加载启动,不应该出现在 define 中的模块代码里。
  • 为了让 sea.js 内部能快速获取到自身路径,推荐手动加上 id 属性:
1
<script src="../gb/sea.js" id="seajsnode"></script>

Sea.js 的调试接口

讲到seajs.use,当然要提一下Sea.js 的调试接口。

  • seajs.cache:Object,查阅当前模块系统中的所有模块信息。
  • seajs.resolve:Function,利用模块系统的内部机制对传入的字符串参数进行路径解析。
  • seajs.require:Function,全局的 require 方法,可用来直接获取模块接口。
  • seajs.data:Object,查看 seajs 所有配置以及一些内部变量的值。
  • seajs.log:Function,由 seajs-log 插件提供。
  • seajs.find:Function,由 seajs-debug 插件提供。

模块加载大体流程

模块加载大体流程:

文字描述:

  1. 通过 use 方法来加载入口模块,并接收一个回调函数, 当模块加载完成, 会调用回调函数,并传入对应的模块作为参数。
  2. 从缓存或创建并加载 来获取到模块后,等待模块(包括模块依赖的模块)加载完成会调用回调函数。
  3. 在图片虚线部分中,加载factory及分析出模块的依赖,按依赖关系递归执行 document.createElement(‘script’) 。

与RequireJS的主要区别

遵循的规范不同

RequireJS 遵循 AMD(异步模块定义)规范,SeaJS 遵循 CMD (通用模块定义)规范

factory 的执行时机不同

SeaJS按需执行依赖避免浪费,但是require时才解析的行为对性能有影响。
SeaJS是异步加载模块的没错, 但执行模块的顺序也是严格按照模块在代码中出现(require)的顺序。

RequireJS更遵从js异步编程方式,提前执行依赖,输出顺序取决于哪个 js 先加载完(不过 RequireJS 从 2.0 开始,也改成可以延迟执行)。如果一定要让 模块B 在 模块A 之后执行,需要在 define 模块时申明依赖,或者通过 require.config 配置依赖。

前端技术 - SeaJS学习的更多相关文章

  1. seaJS学习资料参考

    seajs官方文档:http://seajs.org/docs/#docs http://wenku.it168.com/d_000096482.shtml http://blog.codinglab ...

  2. 百度前端技术学院-基础-day1

    2020.9.14 今天我开始在百度前端技术学院学习基础课程. 先立一个Flag,希望我能在30天之内学完前四十天的课程,后续课程再一天一节. 第一天的内容主要是提供了很多基础学习的网页,比如W3sc ...

  3. 绝版珍珍藏:web前端技术学习指南

    绝版珍珍藏:web前端技术学习指南 优秀的Web前端开发工程师要在知识体系上既要有广度和深度!应该具备快速学习能力. 前端开发工程师不仅要掌握基本的Web前端开发技术,网站性能优化.SEO和服务器端的 ...

  4. 一文读懂前端技术演进:盘点Web前端20年的技术变迁史

    本文原文由作者“司徒正美”发布于公众号“前端你别闹”,即时通讯网收录时有改动,感谢原作者的分享. 1.引言 1990 年,第一个Web浏览器的诞生:1991 年,WWW诞生,这标志着前端技术的开始. ...

  5. SLAM前端技术选择思考

    以前是专门做室内定位技术研究的,先后学习和分析了多种基于电磁的室内定位技术,如WiFi指纹定位(先后出现过RSSI.CTF.CIR多种指纹特征).WiFi ToF定位.低功耗蓝牙BLE以及iBeaco ...

  6. HTML5学堂 全新的HTML5/前端技术分享平台

    HTML5学堂 全新的HTML5/前端技术分享平台 HTML5学堂是做什么的? HTML5学堂~http://www.h5course.com~由多名热爱H5的讲师们组成的一个组织.致力于构建一个前端 ...

  7. 百度前端技术学院(IFE)2016春季学期总结

    今天(5月16日)作为第八个提交者提交了任务五十:RIA微型问卷管理平台 这样一个综合性的大任务,宣告我的IFE春季学期课程学习顺利完成.其实任务五十并不复杂,现在再让我来做,可能一周不到就写出来了, ...

  8. 浅谈web前端就业的学习路线

    初级前端 主要学习三个部分:HTML,CSS,JavaScript 一.html + css部分: 这部分特别简单,到网上搜资料,书籍视频非常多.css中盒子模型,流动,block,inline,层叠 ...

  9. 最受欢迎web前端技术总结

    Web前端技术发展非常快,主流技术的进步.想想刚毕业那会用asp技术.目前,该网站已经非常少见主流应用. 后来的后来J2EE框架.然后SpringMVC声望,然而,最近的各种js框架广泛传播,Html ...

随机推荐

  1. 《机器学习_07_01_svm_硬间隔支持向量机与SMO》

    一.简介 支持向量机(svm)的想法与前面介绍的感知机模型类似,找一个超平面将正负样本分开,但svm的想法要更深入了一步,它要求正负样本中离超平面最近的点的距离要尽可能的大,所以svm模型建模可以分为 ...

  2. React Native 架构演进

    写在前面 上一篇(React Native 架构一览)从设计.线程模型等方面介绍了 React Native 的现有架构,本篇将分析这种架构的局限性,以及 React Native 正在进行的架构升级 ...

  3. poj1780欧拉回路

    转载 #include<cstdio> #include<cstring> ; bool vis[N]; char ans[N]; int main() { int n; wh ...

  4. python之Phantomjs无界面浏览器引擎自动化测试

    文字搬运工,本文主要介绍PhantomJS功能,其中有屏幕快照功能,为后面更新[python接口自动化脚本更新版本],其中新版本中新增自动发送邮件功能正文带图片,使用PhantomJS截取图片后发送邮 ...

  5. 利用Python进行数据分析第六季第七集

    翩翩一叶扁舟载不动许多愁https://www.wenjuan.com/s/uMRVrmv/双肩扛起的是数不尽的忧https://www.wenjuan.com/s/uMRVrmv给我一杯酒喝尽人间仇 ...

  6. win10下安装scrapy出现错误的处理

    一.背景: 在win10的dos窗口下使用命令pip install scrapy安装scrapy时,出现“ error: Microsoft Visual C++ 14.0 is required. ...

  7. 从0开始探究vue-公共变量的管理

    背景 在Vue项目中,我们总会遇到一些公共数据的处理,如方法拦截,全局变量等,本文旨在解决这些问题 解决方案 事件总线 所谓事件总线,就是在当前的Vue实例之外,再创建一个Vue实例来专门进行变量传递 ...

  8. DOM对HTML元素的增删改操作和事件概念和事件监听

    DOM创建节点的方法: document.createElement(Tag),Tag必须是合法的HTML元素 DOM复制节点的方法: 节点cloneNode(boolean deep),当deep为 ...

  9. (三)用less+gulp+requireJs 搭建项目(requireJs)

    首先我想说下我在写js时经常遇到的问题,尤其是很大的项目: 1.我一般会把各个功能分块写在各个js文件中: 比如弹出框: dialog.js $(document).ready(function(){ ...

  10. Java实现 LeetCode 528 按权重随机选择(TreeMap)

    528. 按权重随机选择 给定一个正整数数组 w ,其中 w[i] 代表位置 i 的权重,请写一个函数 pickIndex ,它可以随机地获取位置 i,选取位置 i 的概率与 w[i] 成正比. 说明 ...