公司项目最近需要将js文件迁移到seajs来进行模块化管理,由于我以前主要接触模块化开发是接触的AMD规范的requireJS,没有接触过CMD规范,而且在实际项目中还没有用过类似技术。于是,我非常兴奋的开始了seajs的学习,正好对模块化开发仰慕已久,终于有机会大展身手了!
一开始总是有点曲折的,我照着玉伯的github上的教程一步步来,然后发现在我引入jquery的时候,require到的jquery竟然是undefined,经过一番摸索,我发现原来jquery是基于amd规范的,seajs官网的例子之所以能够成功引入jquery,是因为其jquery是采用cmd规范模块化之后的产物,而显然我从百度cdn上拿下来的jquery是没有经过该处理的。百度了一下,发现jquery想改造成seajs能引入的模块,有至少两种方法
1.在jquery源码外层套上define,将其以cmd的规范模块化
2.找到jquery最后几行的&&amd的条件,可以使用ctrl+f搜索amd即可找到,删掉该条件
显然,第二种方法更为方便,改造之后,果然jquery能够正确引入了,不过据其他部门同事的反馈,改造后的jquery模块在某些情况下会出现莫名其妙的bug,据他说在ios上有bug,由于暂时没遇到bug,因此暂且还是先将jquery也封装为模块
seajs的基本配置还是比较简单的,首先,在最前面先引入seajs本身,这应该是毋庸置疑的,然后开始配置seajs,这里我遇到一个坑,网上部分教程指出config可以使用data-config来引入,写在单独文件里,我愉快的这样做了,然后一直报错,发现路径指向错误,纠结了我半天,最后突然看到原来不知道从哪个新版本开始移除了这个属性,我的天,太逗了
废话少说,正式开始配置
seajs.config({
base:"../sea-modules",
alias:{
"jquery":"jquery/jquery.min.js"
}
});
以下即是seajs常用属性的用法:
base提供基础路径
alias是别名,用于将较长的路径简化 以上两个参数是最基本的参数,实际上还有以下几个参数
paths:用来统一路径前缀,适用于较长的外网前缀
preload:预加载部分模块,貌似已移除
debug:设置为true开启调试模式,在控制台输出一些错误警告
map:将某个路径映射到另一个,常用于在线调试,比如spm构建得到的一般有xx.js和xx-debug.js,此时可用map将.js映射为-debug.js,方便在线调试
vars:设置seajs自带变量,可用{变量名}来获取,常用于模块路径一开始不确定的情况,例如中文或英文,zh-cn或en,该变量是加在路径上的,src="../{变量名}/main.js"
charset:引用script文件时的charset属性,默认为utf-8,该属性可以为函数,具体值为函数返回的值
另外seajs.config函数可以运行多次,多次运行会自动合并配置的参数 配置结束后,开始写入口函数
seajs.use("../static/main");
这是最基本的入口,use方法用来引入模块,此处我引入了main.js,也就是入口js 由于seajs是异步加载模块的,所以这里还可以加入回调函数,传入一个形参,即可获取到main模块,接下来就可以调用main暴露出来的方法 配置完,写完入口,接下来就是重头戏,写模块了 seajs遵循cmd规范,要求每个模块需要按该规范风格书写 即
define(id,dependencies,function(require,exports,module){
//前面两个参数,一个是当前模块唯一标志,一个是当前模块依赖的模块。正常情况下不必指定这两个参数,seajs会帮我们自动获取,第三个factory函数是模块的工厂函数
//require用于获取其他模块,如:
var a = require("moduleA"); //此处require内写的名称可以是具体路径,也可以是alias里定义的别名,一般写的是别名
//通过require语句执行了对应的模块函数,并返回该模块的module.exports对象
//注意,除了返回对象外,也执行了该函数,比如,该模块里如果有一句alert(1)不在exports暴露的方法里,会在require调用的同时直接执行。
a.fn();//获取到a模块后,即可调用a模块暴露出来的方法
})
以下是a模块,同样使用cmd规范
define(function(require,exports,module){
var bb="no bb";
exports.fn=function(){
console.log(bb);
};
});
显然,用脚也能想到控制台会打印 “no bb”, cmd规范里比较重要的概念就是使用exports来暴露属性或方法, 例如exports.a=3,exports.fnn=function(){}, 这样其他模块用require关键字获取到对象的同时,就能使用这些暴露出来的属性或方法了。
可能有人已经注意到了,我们的factory函数里三个参数,前面两个已经用到了,require用来获取模块,exports用来暴露模块,那第三个参数呢,有什么作用?
问得好!其实一开始我也很纳闷,这个玩意到底是干嘛的,经过一番研究,我大体上了解了这个参数 ,原来require获取到的模块实际上最后返回的是module,而调用方法也是通过module.exports获取到的 exports是module.exports的一个引用,至于为什么要拐个弯,我个人猜测有两个原因(作为一个初学者大胆的猜测,如果有误欢迎指正)
1.名字短,写的爽。好吧,我开个玩笑。
2.避免随意改动模块对象,这个才是重点,前面也强调了exports只是一个引用,其指向了module.exports的内存地址 但是引用毕竟是引用,修改引用是不会改动被引用的对象的。
举个例子说明一下。
module.exports=5; exports=3;
此时require后返回的值就会是5,而不会是3,这就是引用和本身最大的区别。
关于这两个的区别有一个新手使用常犯的错误。好吧,我没犯过(得意中~) 某些场景里,我们频繁使用exports向外提供接口,可能写了多个exports.xxx=xxx 。
这个时候,初学者可能会想我可以这样写
exports={
a:xxx,
b:xxx,
c:xxx
}
想想就激动啊,这样写多专业,就好像js面向对象里,给构造函数的prototype拓展方法和属性时,也会用到这种写法 。
然后,很不幸的告诉你,这种写法是错误的,至于原因嘛,还是刚刚提到的知识点,exports仅仅是module.exports的一个引用,改变exports的值并不会影响到module.exports。 所以你费尽千辛万苦简化的代码并没有什么卵用,最后require时引用的module.exports根本没有像你想的那样赋值 。
当然,这种写法的方向是正确的,确实可以简化代码,如果需要这样写,这里一般有两种写法:
方法1:
module.exports={ .... }
这种方法直接给module.exports赋值,一了百了。
方法2:
return{ .... }
利用return返回的内容默认也相当于传入了module.exports 。
到此为止,我们已经能够基本使用require来获取模块,exports来暴露接口。
但是,还没结束呢,在我学习的过程中,可不止引入了一个模块,这个时候,引入多个模块会有一个小问题。
比如
var a=require("modulessA"); var b=require("modulesB");
我引入了两个模块,一个modulesA,一个modulesB,但由于粗心,我写错了第一个模块的名字,此时获取a模块那一行会报错,从而阻塞后续代码的运行 这样会造成很不好的影响,要知道seajs的初衷就是尽量0阻塞 。
此处,seajs提供了require.async方法来异步获取模块,
var a=require.async("modulesssssA");
此时,虽然该行会报错,但不会影响后续代码的执行,这就是异步加载带来的好处,使用async时还可以传入回调函数来指定加载完之后执行的逻辑 。
谈到异步与同步,突然又想起一个需要注意的地方 ,那就是module.exports的赋值必须是同步完成,而不能放在回调函数里,。
例如
setTimeout(function(){
module.exports=...
},0);
此时module.exports会变为 undefined 。
在文章的最后,还提醒大家注意到一个性能问题,那就是seajs模块化项目之后,如果功能较多,大量的模块js加载会造成大量请求,这显然对项目性能是有影响的 。
玉伯本人是推荐是用spm工具来压缩合并这些模块,这样所有的模块会合并到一个js里,适合项目上线使用 至于spm的具体配置,本人就不详细讲解了,百度一下,你就知道。
听我啰嗦了半天,希望初学者能对seajs有充分的了解,我本人也是初次接触,这是我学习了一天之后总结出来的一些基础知识,适用于刚刚上手的朋友,至于大牛们,还请批评指正,毕竟我的理解也比较浅薄,难免有疏漏和表达不当的地方。
最后还啰嗦一句! seajs和requirejs感觉最大的不同在于seajs是按需加载,用到的时候再加载,而requirejs是提前加载,提前就将用到的模块写在一个数组里一开始就加载好, 至于孰优孰劣,在下也不好评价。
seajs学习一天后的总结归纳的更多相关文章
-
seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
-
seaJS学习资料参考
seajs官方文档:http://seajs.org/docs/#docs http://wenku.it168.com/d_000096482.shtml http://blog.codinglab ...
-
seaJs学习笔记之javascript的依赖问题
之前分别为大家介绍了有关javascript中的冲突和性能问题,今天为大家介绍一下有关javascript中的依赖问题.我们将继续就之前javascript中性能问题继续介绍. 先来回顾一下性能问题的 ...
-
C语言学习一个月后感想
C语言学习一个月后感想 感谢李晓东老板及计算机工程师联盟的学长学姐和某神秘同级同学的辛勤指导,感谢宋雨田的督促和陪伴. 初识C的1..体会 我本以为凭借瓜皮思维和花里胡哨操作可以让我熟练地学习语言,现 ...
-
模块化之seaJs学习和使用
使用seaJs也有一阵子了,一直也想抽个时间写个这方面的博客,直到今天才写……也许写的不是很完善,但跟大伙分享也是一种乐趣,不对之处欢迎指出.[抱拳] 时间有限,我这里不过多介绍前端模块化,有兴趣可以 ...
-
seajs学习笔记
seajs配置 seajs.config({ //别名配置 alias:{ 'es5-safe':'gallery/es5-safe/0.9.3/es5-safe', 'jquery':'jquery ...
-
前端MVC学习——模块发开发、seajs学习
这份学习链接已经足够了:http://seajs.org/docs/#intro 我假设你至少已经浏览过上述链接文档.并且掌握了基本的seajs基础知识~ 手把手教你创建helloworld~ Hel ...
-
自学了三天的SeaJs学习,解决了前端的一些问题,与小伙伴们一起分享一下!
我为什么学习SeaJs? [第一]:为了解决项目中资源文件版本号的问题,以及打包压缩合并等问题. [第二]:好奇心和求知欲.[我发现很多知名网站也都在使用(qq空间, msn, 淘宝等等),而且 Se ...
-
seajs教程之seajs学习笔记 seajs.use用法
seajs.use 用来在页面中加载模块.通过 use 方法,可以在页面中加载任意模块. 实例地址:http://www.android100.org/html/201405/23/12807.htm ...
随机推荐
-
C和BlockCode
在使用code block的时候,需要先build,然后再run,否则run的还是上次编译的内容.
-
使用strace追踪多个进程
http://www.ttlsa.com/tools/use-strace-to-track-multiple-processes/ strace是Linux环境下的一款程序调试工具,用来监察一个应 ...
-
“#ifdef __cplusplus extern ";C"; { #endif”的定义
平时我们在linux c平台开发的时候,引用了一些Cpp或者C的代码库,发现一些头文件有如下代码条件编译. #ifdef __cplusplus extern "C" { #end ...
-
标准建立二叉树NEW
#include<iostream> #include<sstream> #include<stdio.h> #include<string> #inc ...
-
八 Appium常用方法介绍
由于appium是扩展了Webdriver协议,所以可以使用webdriver提供的方法,比如在处理webview页面,完全可以使用webdriver中的方法.当然在原生应用中,也可以使用. 1.元素 ...
-
八.django模型系统(二)之常用查询及表关系的实现
Ⅰ.常用查询 1.几个概念 每一个django模型类,都有一个默认的管理器,objects,查询就是依赖于objects管理器进行的(在创建时就被添加了). QuerySet表示数据库中对象的列表( ...
-
JDK源码——单例模式
JDK源码中单例模式的应用 1.Runtime类 Runtime类封装了Java运行时的环境.每一个java程序实际上都是启动了一个JVM进程,那么每个JVM进程都是对应这一个Runtime实例,此实 ...
-
Springboot异常:org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name &#39;userController&#39;
今天本菜鸟编写程序时,遇到了一个异常. org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating ...
-
net core体系-web应用程序-4asp.net core2.0 项目实战(1)-2项目说明和源码下载
本文目录1. 摘要2. Window下运行 3.linux下运行4. 开发记录5. 总结 1.概要 写<Asp.Net Core 2.0 项目实战>系列断断续续已经很长时间了,期间很多朋友 ...
-
[CC-INVENTRY]Arranging the Inventory
[CC-INVENTRY]Arranging the Inventory 题目大意: 有一排长度为\(n(\sum n\le10^6)\)的格子,有些格子是空的,有些格子上有一个箱子. 现在你要用最小 ...