文档章节

Sea.js框架构建

hming
 hming
发布于 2017/03/27 17:20
字数 2965
阅读 10
收藏 0

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.exports
    console.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 code

    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; } );
        }
    }
 })( 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 code

    return jQuery;
 });

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

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

案例分享

案例结构如图: Seajs案例结构.jpg

配置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.js
         base.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.js
          base.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.js
                base.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

© 著作权归作者所有

共有 人打赏支持
hming
粉丝 3
博文 88
码字总数 86648
作品 0
深圳
程序员
私信 提问
2018年web新玩法

摘要:web更新的速度都能赶得上火车的速度,稍有不慎就会掉队,在这里6年前端狗带你分析一下2018年前端的一些新趋势,新变化。 一、typeScript TypeScript 是一种由微软开发的自由和开源的编...

技术金三胖
2018/01/13
0
0
学习 Sea.js 笔记(一)

为学习某开源项目, 里面使用了 sea.js, 为此而学习, 网址是: http://seajs.org/docs/#docs 模块化的价值 (解决什么问题): 命名冲突问题. 命名空间可缓解冲突, 但太长难记忆. 如何优雅地解决?...

刘军兴
2015/11/11
0
0
路由控制和视图转换框架--SPA

概述 SPA是为构建WebApp设计的路由控制和视图转换框架 SPA专注于解决构建WebApp时遇到的共性问题,尤其适用于构建MobileApp, 我们和jQuery Mobile、Sencha Touch等框架不同, 并不是一个构建...

赵达
2013/12/04
3.1K
0
学习 Sea.js 笔记(三)

== require 书写约定 == 必须名为 require. define(function(require) { // 正确写法... ... }); 不用修改, 不要重命名 require (可能构造工具会查找名字 require?) 后续文档说是通过正则匹配...

刘军兴
2015/11/11
0
0
sea.js框架下使用别的需要预加载的框架

如何在sea.js框架下使用一些需要预加载jQuery的框架?例如Twitter的bootStrap框架,需要界面已经预加载了jQuery的,如果使用sea.js框架,则bootStrap会因为无法得到jQuyer而报错。如何正确使...

星星之光
2015/04/23
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

【C++】智能指针简述(四):shared_ptr

  在开始本文内容之前,我们再来总结一下,前文内容:   1.智能指针采用RAII机制,在构造对象时进行资源的初始化,析构对象时进行资源的清理及汕尾.   2.auto_ptr防止拷贝后析构释放同一块内...

shzwork
26分钟前
1
0
作为Java程序员这些技术都不会,拿什么去涨薪跳槽?

引言 当下,正面临着近几年来的最严重的互联网寒冬,听得最多的一句话便是:相见于江湖~,缩减HC、裁员不绝于耳,大家都是人心惶惶,年前如此,年后想必肯定又是一场更为惨烈的江湖厮杀。但博...

别打我会飞
49分钟前
2
0
springboot开发之定时器quartz 定时任务调度(压缩版,抽取quartz的单个任务表实现)

前言 老了, 记不住了, 好记性不如烂笔头; 没想到曾经过目不忘的我, 也有这么一天, 岁月蹉跎,学习一天不如一天 难受 Quartz可以用来做什么? Quartz是一个任务调度框架。比如你遇到这样的问题...

尾生
54分钟前
11
0
技术经理平时都干啥?

「技术主管」是开发团队中的某位程序员需要对一起创建系统的整个开发团队负责时所承担的角色。通常他既要对最终交付的软件系统负责,另外也会像一个程序员一样去开发实现系统。 一个技术主管...

春哥大魔王的博客
今天
7
0
java工作流引擎Jflow流程事件和流程节点事件设置

流程实例的引入和设置 关键词: 开源工作流引擎 Java工作流开发 .net开源工作流引擎 流程事件 工作流节点事件 应用场景: 在一些复杂的业务逻辑流程中需要在某个节点或者是流程结束后做一些业...

ccflow周朋
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部