Sea.js框架构建
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框架构建相关推荐
- js 获得明天0点时间戳_Python 3+Django 3 结合Vue.js框架构建前后端分离Web开发平台实战...
点击上方"测试开发技术",选择设为"设为星标" 优质文章,第一时间送达! 学习全文大概需要 12分钟,内容实战性较强. 1. 前言 本篇将基于Python 3. ...
- 基于 Egg.js 框架的 Node.js 服务构建之用户管理设计
转载需经本人同意且标注本文原始地址:https://zhaomenghuan.github.io/blog/nodejs-eggjs-usersytem.html 前言 近来公司需要构建一套 EMM( ...
- 基于 Egg.js 框架的 Node.js 服务构建之用户管理设计 1
前言 近来公司需要构建一套 EMM(Enterprise Mobility Management)的管理平台,就这种面向企业的应用管理本身需要考虑的需求是十分复杂的,技术层面管理端和服务端构建是架构核 ...
- 读玉伯之Sea.js、开源与前端之路
下面是CSDN访谈正文: CSDN:先介绍一下自己和目前的工作吧! 玉伯:我叫王保平,阿里花名玉伯.目前在支付宝前端技术部工作,从事前端基础类库.工具等产品的研发.喜欢编码.热爱思考,努力把每一天过得 ...
- 前端Js框架 UI框架汇总 特性 适用范围 选择
身为一个资深后端工程师,面对层出不穷的前端框架,总让人眼花缭乱,做一个综合解析贴,从全局着眼,让我们明白各种前端框架的应用范围,为如何选择前端框架,从不同的维度提供一些线索,做为一个长期优化贴,欢迎指 ...
- node mongoose_如何使用Express,Mongoose和Socket.io在Node.js中构建实时聊天应用程序
node mongoose by Arun Mathew Kurian 通过阿伦·马修·库里安(Arun Mathew Kurian) 如何使用Express,Mongoose和Socket.io在N ...
- 13 款惊艳的 Node.js 框架——第1部分
2019独角兽企业重金招聘Python工程师标准>>> [编者按]本文作者为 Peter Wayner,主要介绍13款至精至简的 Node.js 框架,帮助你简化高速网站.丰富 AP ...
- Node.js 框架
Node.js的是一个JavaScript平台,它允许你建立大型的Web应用程序. Node.js的框架平台使用JavaScript作为它的脚本语言来构建可伸缩的应用. 当涉及到Web应用程序的开发 ...
- vue事件总线_[面试] 聊聊你对 Vue.js 框架的理解
作者:yacan8 https://github.com/yacan8/blog/issues/26 本文为一次前端技术分享的演讲稿,所以尽力不贴 Vue.js 的源码,因为贴代码在实际分享中,比较枯 ...
最新文章
- 还在加班做数据吗?今天1分钟教你学会用Python轻松玩转Excel
- 在ubuntu16.04中安装apache2+modsecurity以及自定义WAF规则详解
- 目标检测特殊层:PSROIPooling详解
- GBK、GB2312、GB18030
- P3567 [POI2014]KUR-Couriers
- python字典中的值只能是字符串类型_python字典key不能是可以是啥类型
- Android2.2快速入门
- 布林通道参数用20还是26_这样设置均线参数
- windbg --sqlserver 实例 转
- 全面认识scratch
- 设计师提高效率必备的10大在线工具
- 微信号码检测是什么意思
- 10.27 正睿提高9
- AI各领域产业发展现状
- 转自猎豹移动CEO傅盛:深度学习是什么?
- 如何把C盘里的文件默认位置更改到D盘指定目录?
- 佐治亚理工计算机科学录取,留学案例 | 佐治亚理工大学计算机科学硕士申请条件及案例分享...
- 【读书笔记】Peano公理(为什么“数学归纳法”是正确的?为什么“数学归纳法”可以那么用?)
- 推荐系统 - 基于标签的推荐算法
- General Data Protection Regulation (GDPR) (EU) 2016/679 中文版
热门文章
- SSRF - ctfhub -2【FastCGI协议、Redis协议、URL Bypass、数字IP Bypass、302跳转 Bypass、DNS重绑定Bypass】
- 【AE表达式】下载的模板表达式报错?大多数都是小问题!
- java形参和实参的三种传递方式(值传递,地址传递,引用传递)
- 服务器数据丢包是什么原因?服务器丢包怎么解决?
- 【原】拯救你的机械硬盘!
- 人工智能处理的几大基础任务、元宇宙和人工智能
- LQ0270 手机尾数【水题】
- kafka教程之linux安装教程(一)
- 求助 TM1638不能读回按键值
- 基于JAVA某日杂商店进销存管理系统设计计算机毕业设计源码+数据库+lw文档+系统+部署