seajs学习一天后的总结归纳

公司项目最近需要将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"
   }
});

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常用属性的用法

另外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是提前加载,提前就将用到的模块写在一个数组里一开始就加载好,
至于孰优孰劣,在下也不好评价。
 
时间: 2024-10-10 07:32:13

seajs学习一天后的总结归纳的相关文章

seaJs学习笔记2 – seaJs组建库的使用

原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最近在学习seaJs和AngualrJs的指令和服务,感觉angularjs实在太强大了,好吧,步入主题,今天在深入了解seaJs的时候发现了一款神器,不过这款神奇貌似没有更新和维护了,但我测试了一下,还是可以用的. 这款神奇就是SeaJS 组件库 ,Sea.js 是一个适用于 Web 浏览器端的模块

WPF学习- 新建项目后自定义Main()[Type 'App' already defines a member called 'Main' with the same parameter types]

问题点: 在App.xaml.cs中自己添加Main方法,编译会出现如下报错: 错误 CS0111 类型“App”已定义了一个名为“Main”的具有相同参数类型的成员  错误 Type 'App' already defines a member called 'Main' with the same parameter types  错误 CS0017 程序定义了多个入口点.使用 /main (指定包含入口点的类型)进行编译.  原因: 默认方式新建WPF项目时,编译时会自动生成Main方法(

4_1网络学习第一天后感--网络数据下载

4_1网络学习第一天后感--网络数据下载 1.网络数据下载包括同步下载和异步下载,一般是使用异步下载,异步下载可以利用NSURLConnection这个类. 2.有关数据格式,有JSON格式(多数).XML格式.JSON格式如下: {} 代表字典,[] 代表数组 ,“” 代表字符串 , 100  代表NSNumber 3.分析网络接口 如:@"http://iappfree.candou.com:8080/free/applications/limited?currency=rmb&pa

AIX系统学习之-系统升级后软件错误

AIX系统学习之-系统升级后软件错误 系统环境: 操作系统:AIX 5.3.8 Oracle:  Oracle 11gR2 案例分析:      AIX5.3从5300-08升级到5300-09后,直接安装Oracle 11gR2软件,安装后启动sqlplus出现以下错误: [[email protected] ~]$ sqlplus '/as sysdba' Could not load program sqlplus: Symbol resolution failed for /usr/li

模块化之seaJs学习和使用

使用seaJs也有一阵子了,一直也想抽个时间写个这方面的博客,直到今天才写--也许写的不是很完善,但跟大伙分享也是一种乐趣,不对之处欢迎指出.[抱拳] 时间有限,我这里不过多介绍前端模块化,有兴趣可以去了解. 一.写在前面 seaJs出自前端工程师玉伯之手,一个文件就是一个模块,实现JavaScript的模块化及按模块加载.使用SeaJS可以提高JavaScript代码的可读性和清晰度,确保各个JS文件先后加载的顺序,解决目前JavaScript编程中普遍存在的依赖关系混乱和代码纠缠等问题,方便

C语言学习一个月后感想

C语言学习一个月后感想 感谢李晓东老板及计算机工程师联盟的学长学姐和某神秘同级同学的辛勤指导,感谢宋雨田的督促和陪伴. 初识C的1..体会 我本以为凭借瓜皮思维和花里胡哨操作可以让我熟练地学习语言,现在发现只是python的易入门给我的错觉...错用列表赋值带来的稀奇古怪的初始值,scanf中百度已经无法解决的错误,时不时崩溃的codeblock,我永远无法知道到底在那里出错的oj(wa,时间溢出,数据溢出,编译错误)······好吧我知道这不是问题.(??へ??╬) 但愿吧. 我是贝尔格里尔斯

linux基础学习——克隆备份后网卡不能启动

今天在练习的时候突然想到如果当前使用的虚拟机中的系统坏掉或者出现未知的故障而影响学习进度怎么办,毕竟重装一次系统要耽误不少时间,于是想把当前使用正常的系统COPY一个备份 COPY完之后用VMware打开并更改名字,开机OK,登录OK,测试网络faile--重启网卡 提示"Device eth0 does not seem to be present,delaying initialization" 仔细想想,克隆备份--哦,网卡设置肯定不对,可当前这台虚拟机的网卡相关信息去哪儿找呢

seajs学习笔记一

一.模块化管理的重要性     1.解决冲突问题 2.解决性能问题 3.解决依赖问题 二.为何选择seajs 1.有完整的中文文档 2.符合中国国情 三.seajs如何使用 1.引入seajs库文件 2.如何变成模块 define /*引入好seajs后如何将js文件变成模块*/ define(function(require,exports,module){ /*require,exports,module-seajs规定写法不可修改,变值,重命名*/ /*exports:对外接口 */ fu

seajs学习--module-id 规范

大家相信现在已经能够用seajs完成一个项目了,但是此时的项目离正式上线还有很多差距,还需做很多优化,譬如,优化请求次数,优化文件大小. 当你使用seajs愉快的编码的时候,你也就会发现模块实在是太多了,请求数目过多这一问题.在这章,我们来共同探讨一下怎么优化seajs工程,使之真正可以达到可以上线的标准. 在进行优化以前,我们先讨论一下seajs里边的模块ID,还记得前面说过CMD的模块定义吗?define(id?deps?,factory),这里边的模块ID,官方建议我们不要写,通过工具去生