`
zhouyrt
  • 浏览: 1127121 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JavaScript模块化开发库之SeaJS

 
阅读更多

SeaJS由国内的牛人lifesinger开发。目前版本是1.1.1,源码不到1500行,压缩后才4k,质量极高。

 

这篇会讲述SeaJS的一些基本用法,不会面面俱到,但会就个人的理解讲述官方文档没有提到的一些细节。

 

一、SeaJS的全局接口

 

SeaJS向全局公开了两个标识符: seajs 和 define。

 

如果你的项目中已经用了标识符seajs,又不想改。这时SeaJS可以让出全局的seajs。如

var boot = seajs.noConflict();

这时boot就相当于先前的seajs。

 

如果你的项目中连标识符define也用到了,也不想改。SeaJS是很宽容的,它的define也可以让出。如

 

var boot = seajs.noConflict(true);

较上面仅多传了一个true。这时全局的define也没了。这时需要用boot.define来代替之前的define。

 

用过jQuery的同学应该很熟悉$.noConflict方法,SeaJS的noConflict与之类似。

 

 

 

二、SeaJS的模块写法

 

SeaJS默认使用全局的define函数写模块(可把define当成语法关键字),define定义了三个形参id, deps, factory。

 

define(id?, deps?, factory);

 

这个define很容易让你想起AMD的唯一API:define函数。 或者说让人费解,导致搞不懂SeaJS和 RequireJS define的区别。

 

它们都有个全局的define,形参都是三个,且对应的形参名也一样,会误认为SeaJS也是AMD的实现。

 

事实上SeaJS和RequireJS的define前两个参数的确一样。

 

id都为字符串,都遵循 Module Identifiers。deps都是指依赖模块,类型都为数组。区别仅在于第三个参数factory,虽然类型也都是函数,但其参数意义却不同。

 

RequireJS中factory的参数有两种情况

 

a、和deps(数组)元素一一对应。即deps有几个,factory的实参就有几个。

define(['a', 'b'], function(a, b){
	// todo
});

 

b、固定为require,exports, module(modules/wrappings格式)。

define(function(require, exports, module){
	// todo
});

 

这种方式是RequireJS后期向 Modules/Wrappings 的妥协,即兼容了它。而SeaJS的define仅支持RequireJS的第二种写法:Modules/Wrappings。

 

注意:SeaJS遵循的是 Modules/Wrappings 和 Modules/1.1.1。这两个规范中都没有提到define关键字,Modules/Wrapping中定义模块要求使用的是module.declare而非define。而恰恰只有AMD规范中有define的定义。即虽然SeaJS不是AMD的实现,但它却采用了让人极容易误解的标识符define。

 

 

说了这么多,还没开始写一个模块。下面我们从最简单的开始

 

1、简单模块

 

define({
	addEvent: function(el, type, fn){},
	removeEvent: function(el, type, fn){},
	fireEvent: function(el, type){}
});

这样就写了一个事件模块,这和写一个单例没有区别。更多的时候用该方式定义纯数据模块。它类似于

var E = {
	addEvent: function(el, type, fn){},
	removeEvent: function(el, type, fn){},
	fireEvent: function(el, type){}
};

 

 

2、简单的包装模块

 

define(function() {
	// 一些内部辅助函数
	// ...
	function addEvent() {
		// ..
	}
	function removeEvent() {
		// ..
	}
	function fireEvent() {
		// ..
	}
	return {
		addEvent: addEvent,
		removeEvent: removeEvent,
		fireEvent: fireEvent
	};
});

 

您懂的,在这个匿名函数中可以做很多事情。最后只需公开必要的接口。它类似于

var E = function() {
	// 一些内部辅助函数
	// ...
	function addEvent() {
		// ..
	}
	function removeEvent() {
		// ..
	}
	function fireEvent() {
		// ..
	}
	return {
		addEvent: addEvent,
		removeEvent: removeEvent,
		fireEvent: fireEvent
	};
}();

 

 

3、NodeJS风格的包装模块

 

上面两种写法看不到一丝NodeJS风格(Modules/1.1.1),改写下与“方式2”等价的。

define(function(require, exports) {
	// 一些内部辅助函数
	// ...
	function addEvent() {
		// ..
	}
	function removeEvent() {
		// ..
	}
	function fireEvent() {
		// ..
	}
	// 使用exports导出模块接口,而非返回一个对象
	exports.addEvent = addEvent;
	exports.addEvent = removeEvent;
	exports.addEvent = fireEvent;
});

 

可以看到与“方式2”区别在于:匿名函数有两个参数require、exports。这里导出接口不是return一个对象而是使用exports。而exports不正是NodeJS的风格吗? 细心的同学可能发现这个示例中require参数没有用到,这正是下面要讲的。

 

 

4、有依赖的模块

 

SeaJS中“依赖”都需要使用require函数去获取,虽然SeaJS的define的第二个参数deps也有“依赖”的意思,但它是提供打包工具(SPM)用的。此外,SeaJS的require是作为参数传入匿名函数内的,RequireJS的require则是全局变量。

 

上面定义的是一个没有依赖的模块,以下是有依赖的模块。

define(function(require, exports) {
	var cache = require('cache');
	
	// ...
	
	exports.bind = bind;
	exports.unbind = unbind;
	exports.trigger = trigger;
});

该事件模块依赖于cache模块,函数有两个形参require和exports。抛开外层的匿名函数及define,它就是标准的NodeJS格式:使用require函数取依赖模块,使用exports导出现有模块接口。

 

实际上在SeaJS中具有依赖的模块必须按“方式4”写,即必须是包装模块,且匿名函数的第一个参数必须是标识符 “require”。即可以把require当初语法关键字来使用,虽然它不是全局的。

 

下面我们看看匿名函数的参数require和exports的一些有趣现象

 

a、如果写的不是require,改成req会是什么结果。

define(function(req, exports) {
	var cache = req('cache');
	
	// ...
	
	exports.bind = bind;
	exports.unbind = unbind;
	exports.trigger = trigger;
});

 

Firebug网络请求如下

会看到依赖的“cache”没有被加载,当然JS肯定会报错了。

 

 

b、只把匿名函数的形参改成req,函数内部仍然使用require。

define(function(req, exports) {
	var cache = require('cache');
	
	// ...
	
	exports.bind = bind;
	exports.unbind = unbind;
	exports.trigger = trigger;
});

 

看网络请求

这次“cache”模块竟然请求下来了。

 

仔细看上面的匿名函数代码中require没声明,且形参req而非require。那

var cache = require('cache');

中的require从何而来?

 

看SeaJS源码可知,它的define函数中会取该匿名函数的toString,使用正则匹配解析出其中的“cache”(私有的parseDependencies函数)。

 

我们也看到,虽然cache请求下来了,却仍然报错,因为在执行阶段require是未定义的。因此写依赖模块时匿名函数的第一个参数必须为require且不能更改。

 

正因为使用factory.toString和正则解析依赖,因此require的参数不能是表达式,如

// require的参数不能是表达式运算
require("ui-" + "dialog"); 

 

也不能使用require的别名,如

 

// 不能将require赋值给另外一个变量
var req = require;
req("ui-dialog");
   

 

c、修改exports为expo

define(function(require, expo) {
	var cache = require('cache');
	
	// ...
	
	expo.bind = bind;
	expo.unbind = unbind;
	expo.trigger = trigger;
});

运行是没有问题的。即第二个参数“exports”是可以自定义的。显然SeaJS不赞成改“exports”为其它,这样明显破坏了NodeJS风格(Modules/1.1.1)的模块规范---它们正是使用“exports”导出模块接口。但这点在SeaJS中却无法被强制执行,只能是人为约定。

 

 

5、混合写法的模块

 

上面已经介绍了各种情形中的模块写法。为了与NodeJS风格保持一致:使用require获取“依赖”,使用exports导出“接口”。SeaJS在获取依赖这一块做了限制,即必须使用require。但导出则不一定非得使用exports,即exports可以改为其它。甚至还可以直接使用 “返回值”。

define(function(require) {
	var cache = require('cache');
	
	// ...
	
	// 使用返回值导出接口
	return {
		bind: function() {},
		unbind: function() {},
		fire: function() {}
	};
});
 

我们知道在NodeJS中模块只能是一个对象。即总是往exports上挂方法。SeaJS中如果使用exports导出接口,那么也一样,模块也只能是JS对象。如果使用“返回值”导出接口的话,那么模块可以是任意的JS类型。如下将返回一个函数类型的模块。

define(function(require) {
	var cache = require('cache');
	
	function ad() {
		//...
	}
	
	// 函数类型的模块
	return ad;
});
 

 

 

三、SeaJS的加载方式

 

虽然它提供各种方式(同步异步)加载,最简单的莫过于直接在页面中写script标签。引入SeaJS后,入门多数时候就是seajs.use方法。

 

seajs.use有两个参数,第一个参数可以为字符串(模块名)或数组(多个模块)。第二个参数是回调函数。模块加载后的回调。回调函数的参数与第一个参数一一对应。

seajs.use('dom', function(dom) {
	// todo with dom
});

 

如下将在回调函数中使用dom模块。当然它也提供了快捷方式data-main(同RequireJS)。

 

 

 

 

 

 

 

  • 大小: 13 KB
  • 大小: 11.5 KB
分享到:
评论

相关推荐

    鸡国大冒险运行程序,点开即用

    基于Python+Flask的安全多方计算的隐私保护系统设计与实现+全部资料齐全+部署文档.zip

    【资源说明】 基于Python+Flask的安全多方计算的隐私保护系统设计与实现+全部资料齐全+部署文档.zip基于Python+Flask的安全多方计算的隐私保护系统设计与实现+全部资料齐全+部署文档.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    聊天系统(java+applet).zip

    聊天系统(java+applet)

    setuptools-11.0-py2.py3-none-any.whl

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于UCI Heart Disease数据集的心脏病分析python源码+数据集+演示ppt+详细资料.zip

    基于UCI Heart Disease数据集的心脏病分析python源码+数据集+演示ppt+详细资料.zip基于UCI Heart Disease数据集的心脏病分析python源码+数据集+演示ppt+详细资料.zip基于UCI Heart Disease数据集的心脏病分析python源码+数据集+演示ppt+详细资料.zip基于UCI Heart Disease数据集的心脏病分析python源码+数据集+演示ppt+详细资料.zip基于UCI Heart Disease数据集的心脏病分析python源码+数据集+演示ppt+详细资料.zip基于UCI Heart Disease数据集的心脏病分析python源码+数据集+演示ppt+详细资料.zip基于UCI Heart Disease数据集的心脏病分析python源码+数据集+演示ppt+详细资料.zip基于UCI Heart Disease数据集的心脏病分析python源码+数据集+演示ppt+详细资料.zip

    setuptools-1.3.1-py2.py3-none-any.whl

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    setuptools-40.3.0-py2.py3-none-any.whl

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    公开整理-各省碳排放数据集(1990-2022年).xlsx

    详细介绍及样例数据:https://blog.csdn.net/li514006030/article/details/138872006

    基于Java的两个通用安全模块的设计与实现.zip

    基于Java的两个通用安全模块的设计与实现

    setuptools-14.1.1-py2.py3-none-any.whl

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    华为-智慧园区数字平台技术qytp.pptx

    华为-智慧园区数字平台技术qytp.pptx

    30个Python游戏源码

    30个Python游戏源码

    基于python深度度量学习准确预测蛋白质二级结构源码.zip

    基于python深度度量学习准确预测蛋白质二级结构源码.zip基于python深度度量学习准确预测蛋白质二级结构源码.zip基于python深度度量学习准确预测蛋白质二级结构源码.zip基于python深度度量学习准确预测蛋白质二级结构源码.zip基于python深度度量学习准确预测蛋白质二级结构源码.zip基于python深度度量学习准确预测蛋白质二级结构源码.zip基于python深度度量学习准确预测蛋白质二级结构源码.zip基于python深度度量学习准确预测蛋白质二级结构源码.zip

    基于单片机的语音存储与重放系统.zip

    基于单片机的系统

    Java项目之jspm房屋租赁系统(源码 + 说明文档)

    Java项目之jspm房屋租赁系统(源码 + 说明文档) 2开发技术介绍 6 2.1B/S架构 6 2.2Java技术 6 2.3MySQL介绍 6 2.4MySQL环境配置 7 2.5JSP技术介绍 7 3系统分析 8 3.1可行性分析 8 3.1.1技术可行性 8 3.1.2经济可行性 8 3.1.3操作可行性 8 3.1.4运行可行性 9 3.2系统性能需求分析 9 3.3系统功能分析 9 3.4系统流程的分析 10 3.4.1用户管理的流程 11 3.4.2个人中心管理流程 12 3.4.3登录流程 12 4系统设计 13 4.1软件功能模块设计 13 4.2数据库设计与实现 13 4.2.1概念模型设计 13 4.2.2物理模型设计 15 5系统详细设计 22 5.1系统功能模块 22 5.2管理员功能模块 23 5.3租客功能模块 27 6系统测试 28 7总结与心得体会 29 7.1总结 29 7.2心得体会 29

    小红书-课程网盘链接提取码下载 (2).txt

    小红书-课程网盘链接提取码下载 (2).txt

    setuptools-24.1.1.tar.gz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    c-master (2).zip

    c语言

    setuptools-19.4.1-py2.py3-none-any.whl

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    python企业编码管理的程序(可执行程序+源码).zip

    具体的操作步骤如下: (1)生成6位数字防伪编码。当用户在主程序界面中输入数字“1”菜单项时,将进入“生成6位数字防伪编码 (213563型)”的功能执行任务。此时要求输入生成防伪码的数量,可以根据需要输入生成防伪码的数量,如图2所示。按下<Enter>键,开始批量生成防伪码,生成后系统将提示用户生成了多少个注册码和生成文件的位置信息等,如图3所示。单击“确定”按钮,关闭提示信息。在屏幕上可以看到生成的防伪码信息,如图4所示。生成的文件在程序所在目录下的“codepath”文件夹下,名称为“scode1.txt”,如图5所示。

Global site tag (gtag.js) - Google Analytics