前端技术层出不穷,js模块化更是大势所趋,乱世必出英雄,seajs就是js模块化的佼佼者。
文章适合初学者,大神请绕过。对于一个新技术的学习,主要会讲
->seajs定义及作用
->为何要用seajs
->seajs如何使用之理论篇
->seajs理论偏使用拓展之spm3
->seajs如何使用之实践篇
->seajs文章推荐。
二、seajs定义及作用?1,看下百度释义:
SeaJS是一个遵循CMD规范的JavaScript模块加载框架,可以实现JavaScript的模块化开发及加载机制。主要目的是令JavaScript开发模块化并可以轻松愉悦进行加载,将前端工程师从繁重的JavaScript文件及对象依赖处理中解放出来,可以专注于代码本身的逻辑。SeaJS可以与jQuery这类框架完美集成。使用SeaJS可以提高JavaScript代码的可读性和清晰度,解决目前JavaScript编程中普遍存在的依赖关系混乱和代码纠缠等问题,方便代码的编写和维护。SeaJS的作者是前淘宝UED,现支付宝前端工程师玉伯。SeaJS本身遵循KISS(Keep It Simple,Stupid)理念进行开发,其本身仅有个位数的API,因此学习起来毫无压力。在学习SeaJS的过程中,处处能感受到KISS原则的精髓——仅做一件事,做好一件事。
2,说人话:
seajs就是一个js文件,使用它可以方便管理其它js代码,提高开发效率,易学易用。
三、为何要用seajs?
js的发展不同于其它后台语言,没有模块化的概念,代码混乱且不易维护,从而使得js一度被认为是一门玩具语言。nodejs的出现,将js推向了舞台中央,于是一发不可收拾。社区论坛活跃度成指数函数递增(夸张下),不管前端还是后端,不会写两行js代码都不好意思说自己是程序员。就在这个大背景下,急需出现一种能让js也模块化开发的工具,从而减少依赖和命名冲突。时势造英雄,于是乎,seajs应运而生。
什么?没听懂?来,我告诉你,其实就是解决js的两个大问题:命名空间冲突和文件依赖
附文章一篇http://chaoskeh.com/blog/why-seajs.html进一步确认自己需要使用seajs进行js开发了。
四、seajs如何使用理论偏?
说的比唱的好听,那该怎么使用呢?
1,seajs修炼第一重:下载并引入seajs
官网下载:http://seajs.org/docs/#downloads
下载后会看到dist目录下有个sea.js,对就是他,我们的英雄小哪吒,在项目中引入它就可以了。
为了让 sea.js内部能快速获取到自身路径,推荐手动加上 id 属性,这对性能和稳定性会有一定提升,推荐默认都加上。
<script src="js/sea.js" id="seajsnode"></script>
2,seajs修炼第二重:使用seajs函数“define”(函数基本就这一个)说明:使用define函数来定义一个模块,据CMD规范。一个文件就是一个模块。所以一个js文件中只有一个define。SeaJS中模块的概念有点类似于面向对象中的类——模块可以拥有数据和方法,数据和方法可以定义为公共或私有,公共数据和方法可以供别的模块调用。
1)define是如何处理参数的:
fn.define = function(id, deps, factory)
define可以接收的参数分别是模块ID,依赖模块数组及工厂函数;
如果只有一个参数,则赋值给factory。
如果有两个参数,第二个赋值给factory;第一个如果是array则赋值给deps,否则赋值给id。
如果有三个参数,则分别赋值给id,deps和factory。
2)定义一个模块
define(function(require,exports, module) {
var a = require('./a');//引入a模块 即引入a.js,js文件后缀名可省略
//require是同步的 所以下面可以使用require过来的模块
a.fun1();//调用a.js里面定义并暴露给外部的fun1函数
a.name;//调用a.js里面定义并暴露给外部的fun1属性
var data1 = 1; //私有属性
var func1 = function() { //私有方法
exports.name='定义name属性暴露给外部';
exports.fun2= function(){
console.log('定义了fun2函数并通过exports暴露给外部');
}
});
require——记载依赖模块。通过这个参数来进行对其他模块的加载。
exports——接口点,将数据或方法定义在其上则将其暴露给外部调用。
module——模块的元数据。是一个对象,有属性:
module.id——模块的ID。
module.dependencies储了此模块依赖的所有模块的ID列表的一个数组。
module.exports——与exports指向同一个对象。
3)除了外面多了一层define(function(){});其他使用类似nodejs
4)除了使用exports来向外部暴露属性方法还可以使用return
5)当return语句是模块的唯一代码,可以直接返回一个json对象
define({
data: 1,
func:function() {
return'hello';
}
});
3,seajs修炼第三重:熟悉require对象
require对象进行加载依赖的模块,或者可以使用require.async('./a')来进行异步加载,即当使用到的时候才进行加载。
加载完成后的回调函数
require('./a',function(a){});
使用require对象来进行加载模块,其实使用正则表达式进行验证加载的,所以其参数必须是特定的字符串,不能是表达式。
4,seajs修炼第四重:使用seajs.config进行全局配置
seajs.config({
//Sea.js 的基础路径
//Sea.js 在解析顶级标识时,会相对 base 路径来解析。详情请参阅 模块标识
//注意:一般请不要配置 base 路径,把 sea.js 放在合适的路径往往更简单一致。
base:'src/js/jslib/',
//对较长的常用路径设置别名。
alias: {
'app':'src/js/app/'
},
//获取js时script标签的charset属性
charset:'utf-8',
//待脚本加载的最长时间,以毫秒为单位。
timeout: 20000,
//值为 true 时,加载器会使用 console.log 输出所有警告和错误。 默认为 false, 加载器只抛出异常。另外,还可以将 debug 值设为2。
//这种情况下, 每个脚本请求都会加上唯一时间戳。这在测试期间很有用,可以强制浏览器每次都请求最新版本。
debug:false,
//普通模块加载前,提前加载初始化特定模块。
preload: [ // 在老浏览器中,提前加载好ES5和json模块:
Function.prototype.bind ? '' : 'es5-safe',
this.JSON ? '' : 'json'
],
// 变量配置
vars: {
'locale': 'zh-cn'
},
// 映射配置
map: [
['http://example.com/js/app/', 'http://localhost/js/app/']
]
});
5,seajs修炼第五重:使用seajs.use 载入入口模块
//单模块模式
seajs.use('./a');
//回调模式
seajs.use('./a',function(a){
a.dosomething();
});
//多模块模式
seajs.use(['./a','./b'],function(a,b) {
a.dosomething();
b.dosomething();
});
6,seajs修炼第六重:注意事项
1)Sea.js模块文件推荐下面写法
define(function(require, exports, module) {
// 模块代码
});
2)seajs配合现有js使用
define(function() {
//现有js代码
return $.noConflict();
});
如:var $ = require('./jquery');
//加载jquery返回值为null
//解决方法
define(function(){
//jquery源代码
return $.noConflict();
});
3)module.exports通常用于对外提供对象
define(function(require, exports, module) {
var obj={};
obj.name='abc';
obj.fun1=function(){};
module.exports=obj;
});
4)版本差异
2.1.0版
去除 data-main、data-config 等语法糖功能,保持简单纯粹。
2.3.0
去掉css支持,推荐link标签同步引入。如果实在要用,可以用seajs-css插件来完成。
preload移除,推荐script标签同步引入。如果实在要用,可以用seajs-preload插件来完成。
去掉根据 sea.js 路径自动猜测 base 路径的功能。交给用户自己配置。
五、seajs理论偏使用拓展之spm3
使用seajs写好的程序会发现很多js文件,这样直接发布项目服务器请求这么多次肯定是不友好的,当然seajs也意识到了这个问题,使用spm3可以合并压缩seajs的众多js文件。
spm3是seajs修炼第七重,也是最后一层。
下面介绍下spm3的使用方法:
1、基于nodejs 需安装nodejs 可输入node -v测试
2、然后安装spm
npm install spm -g
3、查看安装版本spm -v
4、在项目下创建package.json 也可以用 npm init
{
"name": "mizi",
"version": "1.0.0",
"description": "with seajs",
"author": "haha",
"license": "MIT",
"spm": {
"main": "static/js/main.js"
}
}
spm 字段是包含与 spm 构建相关的一些属性。这里把入口文件定义为 main.js (默认为 index.js)
main入口文件,要压缩的文件
5、执行
spm build
6、构建完成修改下页面引入js的路径
如若不能运行但不报错可能是因为:
spm3 当中,支持的书写规范从 CMD 模块 转向了 CommonJS。因此在构建之前,要先把原 CMD 模块的 define 包装去掉。构建之后 spm3 会自动在代码外添加。
包装(如果没有去掉,构建后会发现原 define 外又添加了一层 define,会导致代码不能执行)。
作者疑问
1、为何我本地只生成了一个main.js 并没有生成main-debug.js呢。
2、上面的即使不去掉 define 包装也是可以用的呀,亲测。
3、命令行输入 spm init 并没有资料上说的那种会构建很多代码
分析:是不是因为我spm3用的是3.9.0版本导致
还请看到并知道的不吝留言告知
六、seajs如何使用之实践篇
通过两个例子加强下seajs和spm3的使用吧
github例子源码
七、seajs文章推荐:很多还没讲到,下面推荐seajs更多资料
seajs官方文档:http://seajs.org/docs/
深入探寻seajs的模块化与加载方式:http://www.jb51.net/article/64024.htm
《Hello Sea.js》入门指南:http://island205.github.io/HelloSea.js/
2016-10-13 10:01