由来:javascript
在软件开发过程当中,模块化编程思想已经习觉得常了,模块化编程不只仅给开发团队带来效率方面上的好处,还可以让开发的项目或者产品维护成本大大下降。html
那么,在WEB开发过程当中JS脚本语言已经不可或缺了,经过JS脚本语言可以带来更加温馨的人机交互和用户体验。可是,JS脚本的使用过程当中也会有出现引用依赖的混乱,那么JS脚本语言的模块化思想势必会获得你们普遍的承认,在这样的一个背景下,淘宝前端工程师玉伯带来了SeaJS脚本语言,让模块化编程思想进入到JS脚本的世界里。前端
特色:java
SeaJS是一个遵循CommonJS规范的JavaScript模块加载框架,能够实现JavaScript的模块化开发及加载机制。与jQuery等JavaScript框架不一样,SeaJS不会扩展封装语言特性,而只是实现JavaScript的模块化及按模块加载。SeaJS的主要目的是令JavaScript开发模块化并能够轻松愉悦进行加载,将前端工程师从繁重的JavaScript文件及对象依赖处理中解放出来,能够专一于代码自己的逻辑。SeaJS能够与jQuery这类框架完美集成。使用SeaJS能够提升JavaScript代码的可读性和清晰度,解决目前JavaScript编程中广泛存在的依赖关系混乱和代码纠缠等问题,方便代码的编写和维护。jquery
SeaJS自己遵循KISS(Keep It Simple, Stupid)理念进行开发,其自己仅有个位数的API,所以学习起来毫无压力。在学习SeaJS的过程当中,到处能感觉到KISS原则的精髓——仅作一件事,作好一件事。算法
优点:从一个例子中来看SeaJS优点,编程
传统模式:前端工程师
var M1={ run:function(){ alert('M1'); M2.run(); } } var M2={ run:function(){ alert('M2'); } } <script src="./M2.js"></script> <script src="./M1.js"></script>
使用SeaJS以后:app
//init.js define(function(require, exports, module) = { var m1=require('M1'); exports.init=function(){ m1.run(); } }); //M1.js define(function(require,exports,module)={ var m2=require('M2'); exports.run=function(){ alert('M1'); m2.run(); } }); define(function(require,exports,module)={ exports.run=function(){ alert('M2'); } }); <script src="./sea.js"></script> <script> seajs.use('./init', function(init) { init.init(); }); </script>
经过两个简单的实例可以看出使用SeaJS以后代码的模块化很是清晰,而且在HTML页面中仅仅引用一个./sea.js文件而且仅仅调用init便可,具体init后面实现的逻辑对用户是透明的。框架
经过这篇博客可以对SeaJS脚本语言有所了解,后面文章介绍利用SeaJS编写模块。
在介绍SeaJS模块编写和引用以前先介绍一下关于SeaJS模块化的使用原则。
使用SeaJS开发JavaScript的基本原则就是:一切皆为模块。引入SeaJS后,编写JavaScript代码就变成了编写一个又一个模块,SeaJS中模块的概念有点相似于面向对象中的类——模块能够拥有数据和方法,数据和方法能够定义为公共或私有,公共数据和方法能够供别的模块调用。另外,每一个模块应该都定义在一个单独js文件中,即一个对应一个模块。
知道了这些以后咱们再来学习模块的编写,载入和引用。
模块编写:
SeaJS中使用define函数定义一个模块。define能够接收三个参数:require, exports, module。
require——模块加载函数,用于记载依赖模块。
exports——接口点,将数据或方法定义在其上则将其暴露给外部调用。
module——模块的元数据。
关于模块的几种写法:
第一种是教科书式的写法,也是最经常使用的一种写法。
define(function(require, exports, module) { var a = require('a'); //引入a模块 var b = require('b'); //引入b模块 var data1 = 1; //私有数据 var func1 = function() { //私有方法 return a.run(data1); } exports.data2 = 2; //公共数据 exports.func2 = function() { //公共方法 return 'hello'; } });
第二种方法是抛弃exports和module的方式:
define(function(require) { var a = require('a'); //引入a模块 var b = require('b'); //引入b模块 var data1 = 1; //私有数据 var func1 = function() { //私有方法 return a.run(data1); } return { data2: 2, func2: function() { return 'hello'; } }; });
第三种方式:相似于JSON写法,其实就是没有方法的一种写法。
define({ data: 1, func: function() { return 'hello'; } });
经过这三种方式应该对模块的编写有所了解了,估计你已经火烧眉毛的想去写几个模块尝试一下了,那就快点来写吧。
SeaJS支持以下几种方式:
第一种:绝对路径--给出js文件的绝对路径
require("http://example/js/a");
第二种:相对路径--用相对调用载入函数所在js文件的相对地址寻找模块
require("./c");
第三种:经过全局变量来匹配相对路径:相对SeaJS全局配置中的“base”来寻址(后面文章会介绍到)
SeaJS提供了三种载入的方式:seajs.use,require和require.async
第一种:seajs.use
seajs.use主要用于载入入口模块。入口模块至关于JAVA程序的main函数,同时也是整个模块依赖树的根。
这种方式有几种写法:
//单一模式 seajs.use('./a'); //回调模式 seajs.use('./a', function(a) { a.run(); }); //多模块模式 seajs.use(['./a', './b'], function(a, b) { a.run(); b.run(); });
通常seajs.use只用在页面载入入口模块,SeaJS会顺着入口模块解析全部依赖模块并将它们加载。若是入口模块只有一个,也能够经过给引入sea.js的script标签加入”data-main”属性来省略seajs.use。
来个小实例来讲明一下:
<!DOCTYPE HTML> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>TinyApp</title> </head> <body> <p class="content"></p> <script src="./sea.js" data-main="./init"></script> </body> </html>
第二种:require
require是SeaJS主要的模块加载方法,当在一个模块中须要用到其它模块时通常用require加载:ar a = require('a'); //引入a模块
第三种:require.async
以前的require方式是一次把全部依赖的JS文件都加载进来,若是想何时用到何时加载的话就会用这种方式,这种方式效率比require高一些。
经过上面的介绍,应该对SeaJS的模块载入和引用有所了解了,其实者经过这几篇的介绍会发现SeaJS的模块化编程思想和它带给开发人员的简单易用的特色。下篇博客介绍一下SeaJS的全局配置。
SeaJS提供了一个seajs.config方法能够设置全局配置,接收一个表示全局配置的配置对象。具体使用方法以下:
seajs.config({ base: 'path/to/jslib/', alias: { 'app': 'path/to/app/' }, charset: 'utf-8', timeout: 20000, debug: false });
若是在JS脚本中引入模块jquery的话,var $ = require('jquery');那么这时候在上篇博客中说道的引入模块的方式之三就能够用全局配置来操做了。
在全局配置中base表示基址寻址时的基址路径。base设置为 http://example.com/js/3-party/ ,那么就会载入base路径下的juery模块。
另外的一些属性的用途为:
alias能够对较长的经常使用路径设置缩写。
charset表示下载js时script标签的charset属性。
timeout表示下载文件的最大时长,以毫秒为单位。
debug表示是否工做在调试模式下。
经过这样的一个全局配置,开发者可以很轻松的将一些很长很繁琐的公用的路径等来提取到全局配置中,减轻了开发者的繁琐的CV(复制、黏贴)操做。
到这里,关于SeaJS简介就介绍完了,咱们会发现这个脚本语言模块化的特色很是突出,而且语言自己比较简单而且上手容易。