2019独角兽企业重金招聘Python工程师标准>>>

CMD模块定义规范

在Sea.js中,所有JavaScript模块都遵循CMD(Common Module Definition)模块定义规范。该规范明确了模块的基本书写
格式和基本交互规则。在CMD规范中,一个模块就是一个文件。

代码的书写格式为:define(factory);

define是一个全局函数,用来定义模块。参数factory,可以是一个函数,也可以是一个对象或字符串。当factory为对象、
字符串时,表示模块的接口就是该对象、字符串。如下:1>.可以定义一个JSON数据模块:define({ "foo": "bar" });2>.也可以定义一个字符串模块:define('My name is Hm.');3>.当factory为函数时,表示是模块的构造方法。执行该构造方法,可以得到模块向外提供的接口。
factory方法在执行时,默认会传入三个参数:require、exports 和 module,如下:define(function(require, exports, module) {//code});

factory函数的参数之require

1.require是factory函数的第一个参数,它是一个方法,接受模块标识作为唯一参数,用来获取其他模块提供的接口。用法如下:

define(function(require, exports, module){// 获取模块a的接口var a = require('a');// 调用模块a的方法a.doSomething();
});

2.require.async方法用来在模块内部异步加载模块,并在加载完成后执行指定回调。callback 参数可选。

define(function(require, exports, module) {// 异步加载b模块,在加载完成时,执行回调require.async('b', function(b) {b.doSomething();});// 异步加载多个模块,在加载完成时,执行回调require.async(['c', 'd'], function(c, d) {c.doSomething();d.doSomething();});
});

注意:require是同步往下执行,require.async则是异步回调执行。require.async一般用来加载可延迟异步加载的模块。

require书写规范

1.模块factory构造方法的第一个参数必须命名为require。

// 错误!
define(function(req) {// code
});
// 正确!
define(function(require) {// code
});

2.不要重命名require函数,或在任何作用域中给require重新赋值。

// 错误!
define(function(req) {// code
});
// 正确!
define(function(require) {// code
});

3.require的参数值必须是字符串直接量。

// 错误!
require(myModule);
// 错误!
require("my-" + "module");
// 错误!
require("MY-MODULE".toLowerCase());
// 正确!
require("my-module");

factory函数的参数之exports

exports是一个对象,用来向外提供模块接口。

define(function(require, exports) {// 对外提供foo属性exports.foo = 'bar';// 对外提供doSomething方法exports.doSomething = function(){};
});

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

factory函数的参数之module

module是一个对象,上面存储了与当前模块相关联的一些属性和方法。1>.module.id:模块的唯一标识。2>.module.uri:根据模块系统的路径解析规则得到的模块绝对路径。3>.module.dependencies:是一个数组,表示当前模块的依赖。4>.module.exports:当前模块对外提供的接口。

传给factory构造方法的exports参数是module.exports对象的一个引用。只通过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.exportsconsole.log(module.exports === exports); // false
});

注意:对module.exports的赋值需要同步执行,不能放在回调函数里。

CMD规范执行流程

模块a.js:

define(function(require,exports,modules){var $ = require('jquery')
})
1>.通过回调函数的Function.toString函数,使用正则表达式来捕捉内部的require字段,找到require('jquery')内部依赖的
模块jquery
2>.根据配置文件,找到jquery的js文件的实际路径
3>.在dom中插入script标签,载入模块指定的js,绑定加载完成的事件,使得加载完成后将js文件绑定到require模块指定的id
(这里就是jquery这个字符串)上
4>.回调函数内部依赖的js全部加载(暂不调用)完后,调用回调函数
5>.当回调函数调用require('jquery'),即执行绑定在'jquery'这个id上的js文件,即刻执行,并将返回值传给var $

sea.js框架构建

sea.js的引入

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

<script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-debug.js">
</script>

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)

seajs.config常用配置项的配置示例:

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

seajs.config配置可直接使用script标签同步引入:

<script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-config.js">
</script>

sea.js模块的引入

seajs.use: public API,可在全局任何位置调用该方法
<script type="text/javascript">seajs.use('modules/base', function(base) {base.script_load('index');});
</script>

文件后缀的自动添加规则

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

JQ插件模块化

JQ模块化

如果想要将JQ原始文件模块化在sea.js框架中使用,可在原始JQ文件中增加如下代码:

if ( typeof module === "object" && module && typeof module.exports === "object" ) {module.exports = jQuery;
} else {window.jQuery = window.$ = jQuery;if ( typeof define === "function" ) {define( "jquery", [], function () { return jQuery; } );}
}
如下:/*!* jQuery JavaScript Library v1.9.1* http://jquery.com/*/(function( window, undefined ) {// jQ codeif ( typeof module === "object" && module && typeof module.exports === "object" ) {module.exports = jQuery;} else {window.jQuery = window.$ = jQuery;if ( typeof define === "function" ) {define( "jquery", [], function () { return jQuery; } );}}})( window );

如不想模块化JQ也可以直接使用script标签同步引入:

<script type="text/javascript" src="http://localhost/tseajs/static/js/libs/jquery/jquery.js">
</script>

JQ插件模块化

如果想要将JQ插件模块化在sea.js框架中使用,可按照CMD规范将JQ插件定义为JQ插件模块:

如下:define(function (require, exports, module) {var jQuery = require("jquery");//插件如果依赖JQ时,要先引入JQ模块//Plugin codereturn jQuery;});

如不想模块化JQ插件也可以直接使用script标签同步引入:

<script type="text/javascript" src="http://localhost/tseajs/static/js/libs/jquery.validate/jquery.validate.js">
</script>

案例分享

案例结构如图:

配置sea-config

sea-config.js文件的配置如下:

seajs.config({// 别名配置alias: {'jquery': 'libs/jquery/jquery.js','jquery.validate': 'libs/jquery.validate/jquery.validate.js'},// 变量配置vars: {'locale': 'zh-cn'},// 调试模式debug: true,// 基础路径base: 'http://localhost/tseajs/static/js/',// 文件编码charset: 'utf-8'
});

定义主模块

定义主模块base.js文件,如下:

/***项目主模块*/
define(function(require, exports, module) {//加载jquery, 并把$设为全局变量window.$ = window.jQuery = $ = require('jquery');//定义一个全局的模块加载函数.module为模块名,options为参数exports.script_load = function(module, options) {//使用require.async异步加载模块。模块需要提供一个固定的对外调用接口,这里定义为run。require.async('modules/' + module, function(module) {if (typeof(module.run) === 'function') {module.run(options);}});};
});

定义应用模块

定义应用模块index.js文件,如下:

define(function(require, exports, module) {var eventInit = function(){$('#alert').click(function() {alert('test-4');});};exports.run = function(){ //提供对外的调用接口run()$(function(){alert('test-2');alert('test-3');});$(alert('test-1'));eventInit()};
});

在app/index/index.html文件中使用定义的模块:

<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>sea.js应用</title></head><body><button id="alert">点击我</button></body><script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-debug.js"></script><script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-config.js"></script><script type="text/javascript">seajs.use('modules/base', function(base) {//启动主模块base.jsbase.script_load('index');//加载index.js});</script></html>

在浏览器中运行,在控制台中查看元素,通过模块加载器加载了jq文件,如下:

<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>sea.js应用</title><script charset="utf-8" async="" src="http://localhost/tseajs/static/js/modules/base.js"></script>//加载了base.js模块<script charset="utf-8" async="" src="http://localhost/tseajs/static/js/libs/jquery/jquery.js"></script>//加载了jquery.js模块<script charset="utf-8" async="" src="http://localhost/tseajs/static/js/modules/index.js"></script>//加载了index.js模块</head><body><button id="alert">点击我</button><script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-debug.js"></script><script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-config.js"></script><script type="text/javascript">seajs.use('modules/base', function(base) {//启动主模块base.jsbase.script_load('index');//加载index.js});</script></body></html>

运行结果

运行文件后会依此弹出test-1,test-2,test-3,在点击按钮后会弹出test-4

加载JQ插件

定义应用模块login.js文件,如下:

define(function(require, exports, module) {require('jquery.validate');//引入模块化后的jq插件var onReady = function() {$('form.login-form').validate({debug: true,rules: {'[name=username]': {required: true},'[name=password]': {required: true,rangelength:[3,10]}},submitHandler: function(form) {alert("提交表单");form.submit();} });};exports.run = function() {$(onReady());}});

在app/login/index.html文件中使用定义的模块:

<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>validator</title><style type="text/css">//样式定义</style></head><body><div id="form"><form class="login-form" method="post" action=""><input name="username" type="text" required><br /><input name="password" type="password" required><br /><button class="button" type="submit">登陆</button></form></div><script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-debug.js"></script><script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-config.js"></script><script type="text/javascript">seajs.use('modules/base', function(base) {//启动主模块base.jsbase.script_load('login');//加载login.js});</script></body></html>

在浏览器中运行,在控制台中查看元素,通过模块加载器加载了jq文件以及jq插件文件,如下:

<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>validator</title><style type="text/css">//样式定义</style><script charset="utf-8" async="" src="http://localhost/tseajs/static/js/modules/base.js"></script>//加载了base.js模块<script charset="utf-8" async="" src="http://localhost/tseajs/static/js/libs/jquery/jquery.js"></script>//加载了jquery.js模块<script charset="utf-8" async="" src="http://localhost/tseajs/static/js/modules/login.js"></script>//加载了login.js模块<script charset="utf-8" async="" src="http://localhost/tseajs/static/js/libs/jquery.validate/jquery.validate.js"></script>//加载了jquery.validate.js模块
</head>
<body>
<div id="form"><form class="login-form" method="post" action="" novalidate="novalidate"><input name="username" type="text" required=""><br><input name="password" type="password" required=""><br><button class="button" type="submit">登陆</button></form>
</div>
<script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-debug.js"></script>
<script type="text/javascript" src="http://localhost/tseajs/static/js/seajs/sea-config.js"></script>
<script type="text/javascript">seajs.use('modules/base', function(base) {base.script_load('login');});
</script></body>
</html>

运行结果

运行案例,若输入框为空直接点击登陆按钮会提示“This field is required.”;若在输入框中输入内容后再点击登陆按钮则可
正常登陆。

注意:因为jquery.validate.js插件依赖于jquery.js所以引入jquery.validate.js插件前需要先引入jquery.js,因此可在模块化jquery.validate.js插件时,先require("jquery")即可。可参考上面JQ插件模块化部分

相关资料

Seajs 官网 http://seajs.org/docs

Seajs API文档 http://yslove.net/seajs

SeaJS中jQuery插件模块化及其调用方式 http://web322-szb.iteye.com/blog/1742930

转载于:https://my.oschina.net/u/1757002/blog/868538

Sea.js框架构建相关推荐

  1. js 获得明天0点时间戳_Python 3+Django 3 结合Vue.js框架构建前后端分离Web开发平台实战...

    点击上方"测试开发技术",选择设为"设为星标" 优质文章,第一时间送达! 学习全文大概需要 12分钟,内容实战性较强. 1. 前言 本篇将基于Python 3. ...

  2. 基于 Egg.js 框架的 Node.js 服务构建之用户管理设计

    转载需经本人同意且标注本文原始地址:https://zhaomenghuan.github.io/blog/nodejs-eggjs-usersytem.html 前言 近来公司需要构建一套 EMM( ...

  3. 基于 Egg.js 框架的 Node.js 服务构建之用户管理设计 1

    前言 近来公司需要构建一套 EMM(Enterprise Mobility Management)的管理平台,就这种面向企业的应用管理本身需要考虑的需求是十分复杂的,技术层面管理端和服务端构建是架构核 ...

  4. 读玉伯之Sea.js、开源与前端之路

    下面是CSDN访谈正文: CSDN:先介绍一下自己和目前的工作吧! 玉伯:我叫王保平,阿里花名玉伯.目前在支付宝前端技术部工作,从事前端基础类库.工具等产品的研发.喜欢编码.热爱思考,努力把每一天过得 ...

  5. 前端Js框架 UI框架汇总 特性 适用范围 选择

    身为一个资深后端工程师,面对层出不穷的前端框架,总让人眼花缭乱,做一个综合解析贴,从全局着眼,让我们明白各种前端框架的应用范围,为如何选择前端框架,从不同的维度提供一些线索,做为一个长期优化贴,欢迎指 ...

  6. node mongoose_如何使用Express,Mongoose和Socket.io在Node.js中构建实时聊天应用程序

    node mongoose by Arun Mathew Kurian 通过阿伦·马修·库里安(Arun Mathew Kurian) 如何使用Express,Mongoose和Socket.io在N ...

  7. 13 款惊艳的 Node.js 框架——第1部分

    2019独角兽企业重金招聘Python工程师标准>>> [编者按]本文作者为 Peter Wayner,主要介绍13款至精至简的 Node.js 框架,帮助你简化高速网站.丰富 AP ...

  8. Node.js 框架

    Node.js的是一个JavaScript平台,它允许你建立大型的Web应用程序.  Node.js的框架平台使用JavaScript作为它的脚本语言来构建可伸缩的应用. 当涉及到Web应用程序的开发 ...

  9. vue事件总线_[面试] 聊聊你对 Vue.js 框架的理解

    作者:yacan8 https://github.com/yacan8/blog/issues/26 本文为一次前端技术分享的演讲稿,所以尽力不贴 Vue.js 的源码,因为贴代码在实际分享中,比较枯 ...

最新文章

  1. 还在加班做数据吗?今天1分钟教你学会用Python轻松玩转Excel
  2. 在ubuntu16.04中安装apache2+modsecurity以及自定义WAF规则详解
  3. 目标检测特殊层:PSROIPooling详解
  4. GBK、GB2312、GB18030
  5. P3567 [POI2014]KUR-Couriers
  6. python字典中的值只能是字符串类型_python字典key不能是可以是啥类型
  7. Android2.2快速入门
  8. 布林通道参数用20还是26_这样设置均线参数
  9. windbg --sqlserver 实例 转
  10. 全面认识scratch
  11. 设计师提高效率必备的10大在线工具
  12. 微信号码检测是什么意思
  13. 10.27 正睿提高9
  14. AI各领域产业发展现状
  15. 转自猎豹移动CEO傅盛:深度学习是什么?
  16. 如何把C盘里的文件默认位置更改到D盘指定目录?
  17. 佐治亚理工计算机科学录取,留学案例 | 佐治亚理工大学计算机科学硕士申请条件及案例分享...
  18. 【读书笔记】Peano公理(为什么“数学归纳法”是正确的?为什么“数学归纳法”可以那么用?)
  19. 推荐系统 - 基于标签的推荐算法
  20. General Data Protection Regulation (GDPR) (EU) 2016/679 中文版

热门文章

  1. SSRF - ctfhub -2【FastCGI协议、Redis协议、URL Bypass、数字IP Bypass、302跳转 Bypass、DNS重绑定Bypass】
  2. 【AE表达式】下载的模板表达式报错?大多数都是小问题!
  3. java形参和实参的三种传递方式(值传递,地址传递,引用传递)
  4. 服务器数据丢包是什么原因?服务器丢包怎么解决?
  5. 【原】拯救你的机械硬盘!
  6. 人工智能处理的几大基础任务、元宇宙和人工智能
  7. LQ0270 手机尾数【水题】
  8. kafka教程之linux安装教程(一)
  9. 求助 TM1638不能读回按键值
  10. 基于JAVA某日杂商店进销存管理系统设计计算机毕业设计源码+数据库+lw文档+系统+部署