好久好久之前……………………的好久好久的之后,也就是昨天的昨天(2012-07-07),D2前端技术论坛,下午3点,分会场,@老赵分享其开源项目(什么来着?名字彷佛很难记,让我找找~~)Jscex. 印象较深的是末了,其戏称seajs为高富帅。javascript
为什么有此感慨?一样是开源项目,seajs由于①原做者我的影响力②推广渠道或者说团队影响力③背后干爹的大力支持等缘由,其知名度以及接受程度要比Jscex高很多。css
我本身彷佛也有相似的感触,10年年初的时候,我本身折腾了一个关于CSS3的小项目,有别于通常的参考文档,这里容许用户(主要是同行)添加相关的文章,以及一些须要注意的技术点。
html
虽知响应应甚少,然而,几年下来,令我啧舌的是,竟然没有1条更新信息时出自他人之手。头一年,我还乐此不疲地更新相关文章以及本身发现的一些知识注意点,但后来,本身也缴械投降,懒得折腾了,纯碎看成静态的参考文档看了。前端
所谓独木难支,我的的精力老是有限的,影响力也是有限的。不少时候,本身折腾点东西就像鹅毛飘到水里同样,涟漪都没一个,不免心有悸动:要不去傍个高富帅、白富美~~java
哈哈,不过人贵自知,不是人人都能成为郭美美的,沉淀心态,低调蜕变,说不定,之前一些渴求的东西会以附加产物的形式悄悄来到你的身边。node
我记得大学,应该是根叔吧,关于毕业,其说过(大体意思):“若是毕业的时候,你以为你作什么都没有问题,那你就是合格的本科生。”
我将其理解为:毕业真正考量的不是学到了多少东西,而是是否有足够强大的学习能力。css3
很多人询问过我,CSS该怎么学,JS该怎么学?我能回答的可能是,要重视基础,要舍得吃苦~~至于其余的,说得再多,其实也不必定有用。一来每一个人的学习能力与领悟力有差别;二来,本身的学习方法不必定适合他人。指个大方向,应该更有用的,正所谓“师父领进门修行在我的”。git
基础是个很玄妙的东西,扎实的基础犹如武侠里男主角深厚的内功,内功深厚了学什么其余功夫都很快,并且能够很好驾驭;一样,基础扎实,一些新技术什么的上手也快,并且能够自如灵活运用!程序员
前端发展突飞猛进,热门的东西容易产生很强烈的热气,令人产生浮躁之气,尤为对于新手而言,这种燥气是不利的。说不定就会舍本逐末,我忽然想起了@渔人码头以前发过的一个微博——“说实话看了这标题,看了这年龄,看了这评价,我鸭梨山大!鸭梨山大!鸭梨山大!”,图以下:github
所谓“资深”,并非顺应所谓的潮流,追逐一些新东西。这些光鲜亮丽,华而不实的东西,犹如时尚的衣服同样,第二年就老气过期了。潮流一直在前行,而你,却停不了;由于一旦停下来,就落后了,out了,这样的过活是很累的;而实际上,你所掌握的又可能都是些浮于表面的东西,不过却是糊弄糊弄些外行,混口饭吃吃!
貌似扯远了,赶快,用绳子拴住,拉直,用力拉,拉啊,拉……尼玛,终于拉回来了,擦下汗,咱们回到正题,关于seajs. seajs能够算是前端届国产新贵,其年龄(我不肯定)应该小于2岁,不过百度之,能够看到相关的文章仍是很多的,确实有“高富帅”的迹象。seajs主要处理模块加载,基于commonjs规范,使用spm压缩合并颗粒JS模块。
具体如何如何使用,如用法啊,参数啊什么的,能够点击这里的手册进行查看。更深刻的理解能够参考原做者@玉伯也叫射雕在D2上分享的PDF文件(来自微盘)。
下面这篇文章也是很不错的:JavaScript模块化开发库之SeaJS,对模块等对比的分析解释是很受用的。
下面我想讲讲我是如何学习相似seajs这样的新东西。
新东西的学习
1.感性认识,情感化认知
并非全部的程序员都适合作前端,听说,只有20%~30%, 缘由?我想,可能一部分缘由就是情感化思惟,毕竟,咱们所作的东西离用户是很接近的。就我而言,我很在乎一个新事物从总体上给个人feeling, 这种感性的认识可让我准确的把握这个事物的特质,因而会造成更合适的策略处理之。换个容易理解的说法:关于追求新认识的姑娘,我很在乎这个姑娘总体上给个人feeling, 这种感性的认识可让我准确把握这个姑娘的特质,因而,脑中会天然造成更合适的追求策略。微博上不是有这么个段子嘛:追女孩子,若是这个女孩懵懂无知,就带她去看世间繁华;若是这个女孩看尽世间百态,就带她去骑旋转木马!总体感受(感性认识)→类型特质→追求策略。
如今的问题是,若是得到准确的总体feeling呢!道听途说,一面之缘等容易产生误差。咱们须要经过多个途径去了解。首当其冲是官方网站对其描述;而后,就是其余人对其评价,认识等。仍是追妹子例子,去官网至关因而询问其父母对这个姑娘的评价(固然,父母都会惯着本身的孩子,很差的话通常都不会说的);询问其余人就是询问姑娘朋友们、同事们的评价,非诚勿扰不少男嘉宾就死在“好友评价”环节,可见后者仍是相对比较客观的!
所以,反应到现实就是,去官方网站查看,若是是开源项目,也能够去github查看;查看同行们写的相关文章或微博,看看其余人是如何介绍与评价的。
2. 实现方式、API参数
就像咱们使用一个全新的jQuery插件同样,其中必经一步是查看文档,熟悉其API,知道其一些特殊用法等。 比如要熟悉姑娘身高体重,三围,鞋子尺码,知道姑娘的一些癖好等。
3. 实践出真知
古语有云:纸上得来终觉浅,绝知此事要躬行。实践是必须的。为什么?
首先,不少时候,咱们面对一个全新的东西,其文档或手册上API用法、解释等会让咱们不知所云,disorder – 混乱。仿佛回到了大学学“拉普拉斯不等式”的时候,看得头疼。可是,若是你经过本身制做实例,一个一个尝试其所说的内容,不少一眼看上去头疼的东西,立马变得犹如春风拂面。
其次,由于是全新的东西,人总不免被过往的经验(或者说惯性思惟)束缚,有些内容真正意思可能并非脑中所想的那样。举个例子,按照经验式的理解,console.log([2, 10].sort())
的结果应该是[2, 10]
,然而,实际上,在JavaScript中,结果是[10, 2]
, 字符串排序。这种跟以往经验不一样的表现差别须要经过实践才能有切身的体会。
这也是为什么会出现“婚前试爱”这种现象的缘由。
seajs的实践
您可能跟我同样,也是最近才接触seajs, 您可能也跟我同样,被手册上频繁出现的dependencies, factory等词闪花了眼睛。只怪尔等JavaScript不够精深,可是,seajs号称API简单,所以,虽然一些深刻的东西咱们一会儿消化不了,可是,这并不影响咱们使用这个工具。
如何使用?很简单,既然seajs是用来模块化JS的,所以,咱们想一个稍微复杂,又能承受的例子做为实践,从头至尾走一遍,顺便spm也摸索下,若是都经过,天然……你说姑娘都让你实践了,从头至尾都*(和谐)过了,顺便*(和谐)也摸索过了。好了,你们都懂的……
OK, 我想了想,就实现一个简单的弹出框效果,有必定数量的模块JS, 功能实用,且不复杂。下面,若是你是新人,能够跟我一块儿,看看,如何使用seajs模块化相关脚本,同时实现的弹出框效果。
如下实现为本身的思路,可能比较低级与啰嗦,熟悉seajs的人能够直接跳过。
1. 半透明背景遮罩层
说到弹框,首先想到的是后面黑色半透明的遮罩层。咱们就套用:
define(function(require, exports, module) { // 模块代码 });
这种写法应该就能够了,须要暴露的接口直接exports.*
就能够了。
恩,咱们新建一个名叫overlay.js
的JavaScript文件;而后,咱们就着手建立这个遮罩层元素。Wait! 这个建立元素的方法应该模块化,方便其余地方公用,例如弹框中元素建立等。
所以,咱们须要把overlay.js
搁置一边~~
2. 元素建立模块JS
同目录下,新建一个名为elementCreate.js
的JavaScript文件,一样的套用,以下JavaScript代码,注释也要规范哦~~
/** * 建立元素 */ define(function(require, exports) { exports.create = function(tagName, attr) { var element = null; if (typeof tagName === "string") { element = document.createElement(tagName); if (typeof attr === "object") { var keyAttr, keyStyle; for (keyAttr in attr) { if (keyAttr === "styles" && typeof attr[keyAttr] === "object") { // 样式们 for (keyStyle in attr[keyAttr]) { element.style[keyStyle] = attr[keyAttr][keyStyle]; if (keyStyle === "opacity" && window.innerWidth + "" == "undefined") { element.style.filter = "alpha(opacity="+ (attr[keyAttr][keyStyle] * 100) +")"; } } } else { if (keyAttr === "class") { keyAttr = "className"; } element[keyAttr] =attr[keyAttr]attr["class"]; } } } } return element; }; });
exports.create
表示模块暴露在外的方法名称是create
, return element;
表示该方法返回的是建立的元素对象。
3. 回到半透明遮罩层
如今,咱们就可使用elementCreate.js
模块了,要使用这个模块,就得使用require
这个函数(注意:require
名字必须是require
,不能修改)。
var elementCreate = require("./elementCreate");
因而,var element = elementCreate.create("div", {});
就能够建立一个div元素啦!相关完整代码以下(具体遮罩层实现细节能够忽略):
/** * 黑色半透明遮罩层 */ define(function(require, exports, module) { var elementCreate = require("./elementCreate"); var overlay = (function() { var element = elementCreate.create("div", { styles: { display: "none", width: "100%", backgroundColor: "#000", opacity: 0.35, position: "absolute", zIndex: 1, left: 0, top: 0, bottom: 0 } }); document.body.appendChild(element); return { display: false, show: function() { element.style.display = "block"; this.display = true; return this; }, hide: function() { element.style.display = "none"; this.display = false; return this; } }; })(); exports.overlay = overlay; });
您能够狠狠地点击这里:seajs下黑色半透明遮罩效果测试demo
demo页面实际上已经演示了seajs的应用,代码以下:
<script src="sea.js"></script> <script> seajs.use("./overlay", function(overlay) { // overlay.overlay就是遮罩层元素相关对象 }); </script>
4. 弹框了
遮罩层搞定了,下面就是弹框了。咱们新建一个名为”flbox.js
“的js文件。实现弹框效果,首先要黑色半透明层(能够require
overlay.js
模块),而后标题栏,关闭按钮等建立(能够require
elementCreate.js
);最后,弹框里面内容须要Ajax加载,可是,并无ajax的模块,所以,咱们要让ajax模块插下队,先搞定之。
5. ajax模块
由于是示例页面,所以,咱们没有必要写得很完善与详细,这里,咱们就能够单纯实现使用get
方法加载外部一段HTML。因而,捣鼓捣鼓,以下代码:
/** * ajax方法 */ define(function(require, exports) { exports.get = function(url, succCall) { if (url + "" === "undefined") { console.log("请求地址缺失!"); return; } var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200 && typeof succCall === "function") { succCall.call(xhr, xhr.responseText); } }; xhr.open("GET", url, true); xhr.send(); }; });
轻轻松松,您能够狠狠地点击这里:ajax模块测试demo
测试OK,如今回到弹框模块。
6. 弹框模块
下面,须要的模块都有了,咱们只要require
进来,就能够用啦!
require("./elementCreate") require("./ajax") require("./overlay")
虽然,单纯地展现代码我本身也以为挺傻的没劲,可是,对于天地不知的初学者而已,这种喂奶喂到嘴边的方式是他们学习所须要的。
/** * 简易弹框 */ define(function(require, exports) { var funCreate = require("./elementCreate") , funAjax = require("./ajax") , overlay = require("./overlay"); var eleWin = funCreate.create("div", { styles: { display: "none", position: "fixed", left: "50%", zIndex: 2 } }) , eleBar = funCreate.create("div", { styles: { fontSize: "12px", padding: "8px", backgroundColor: "#eee" } }) , eleClose = funCreate.create("a", { href: "javascript:", styles: { fontSize: "12px", color: "#34538b", textDecoration: "none", position: "absolute", margin: "-22px 0 0 85%" } }) , eleBody = funCreate.create("div", { styles: { backgroundColor: "#fff", borderTop: "1px solid #ddd" } }) , eleOverlay = overlay.overlay; eleWin.appendChild(eleBar); eleWin.appendChild(eleClose); eleWin.appendChild(eleBody); document.body.appendChild(eleWin); eleBar.innerHTML = "弹出框"; eleClose.innerHTML = "[关闭]"; eleClose.onclick = function() { flbox.close(); return false; }; var flbox = { loading: function() { eleBody.innerHTML = '<div style="width:200px;height:100px;padding:10px;">加载中...</div>'; this.position(); }, open: function(url) { var self = flbox; funAjax.get(url, function(html) { eleBody.innerHTML = html; self.position(); }); }, position: function() { eleWin.style.display = "block"; eleOverlay.show(); var widthWin = eleWin.clientWidth , heightWin = eleWin.clientHeight; // 定位 eleWin.style.marginLeft = "-" + widthWin / 2 + "px"; eleWin.style.top = (screen.availHeight - heightWin - 100) / 2 + "px"; }, close: function() { eleOverlay.hide(); eleWin.style.display = "none"; eleBody.innerHTML = ""; } } exports.open = flbox.open; });
7. ajax地址增长随机数
为了不弹框打开时IE浏览器下的缓存问题,咱们须要一个url地址增长随机查询字符串的方法。新建名为queryRandom.js
的模块JS文件,键入以下代码:
/** * URL地址后面增长随机参数 */ define(function(require, exports, module) { exports.queryRandom = function(url) { var strQueryRandom = "random=" + Math.random(); var arrQuery = url.split("?"); if (arrQuery[1] != undefined) { // 含查询字符串 if (url.slice(-1) === "&") { url = url + strQueryRandom; } else { url = url + "&" + strQueryRandom; } } else { // 不含查询字符串 url = url + "?" + strQueryRandom; } return url; }; });
您能够狠狠地点击这里:seajs增长随机查询demo
8. 万事具有、终极测试
如今,咱们新建一个主线js, 命名为main.js
, 配合demo页面,咱们写个很简单的方法——即点击某连接,弹框显示该连接href属性所对应的页面内容。
完整代码以下:
/** * 主线js * 点击小图查看大图测试 */ define(function(require, exports) { var query = require("./queryRandom") , flbox = require("./flbox"); exports.bind = function(element) { element.onclick = function() { var href = this.href; flbox.open(query.queryRandom(href)); return false; }; }; });
您能够狠狠地点击这里:seajs实现简易弹框效果demo(不支持IE6浏览器)
而调用的脚本很简单:
seajs.use("./main.js", function(test) { test.bind(document.getElementById("test")); });
这很好地体现的seajs API简单的优势。
因而乎,遵循commonjs写法规范的各个子模块们,在seajs简单的API下,组合出了咱们想要的弹出框效果。而,这些子模块们,又能够被用在其余地方。没有脚本冲突,没有上线时差冲突。可维护性大大提高。这就是seajs的意义所在。
上面简易弹框效果相关代码我已经打包了,点击这里(右键 – [目标|连接]另存为):seajs-flbox.zip
虽说,咱们须要的弹框效果已经实现了,可是,倒是不能直接上线使用的,为什么?
咱们看下其http请求,以下截图:
哎呀呀,这么多JS请求,吓着乌索普脆弱的当心脏了。虽然,seajs模块化的书写提升了维护性,可是,也带来了前端性能的问题!如何解决?
如今,就是救世主spm出场的时候了,spm → seajs package manage?
spm能够合并并压缩seajs中的各个模块JS文件。仍是上面的弹框demo页面,咱们在地址后面增长”?spm=1
“,以下图所示,访问之:
再次刷新页面,查看HTTP请求数,额哈哈,本来6个JS请求,如今合并成1个啦:
命令行中以下代码即实现效果:
spm build main.js --combine --app_url zxx
而后,main.js中所用到的相对路径require的全部模块就会合并并压缩,新生成的文件(若是没有指定输出路径)会是__build/main.js
spm的安装与使用
spm安装与使用github上有介绍。大体以下:
安装
先安装node和npm, http://nodejs.org/#download;而后安装spm, 以下命令行代码:
$ npm install spm -g
build[option]模块
压缩一个JS模块:
$ spm build a.js
压缩并合并:
$ spm build a.js --combine
压缩并合并全部独立模块(包括绝对路径的):
$ spm build a.js --combine_all
清除建立的文件:
$ spm build --clear
经过定义build-config.js
能够作更多的事情:
build-config.js:
module.exports = { "base_path": "/path/to/libs/", "app_url": "http://test.com/js/app/", "app_path": "/path/to/app/", "loader_config": "path/to/init.js" };
更多信息,能够调用:
$ spm help build
以上为我以为经常使用的。这里推荐一篇关于smp使用的文章:seajs的spm使用摸索。这篇文章对spm各个参数都有解释,另外,还提供了自定义输出路径等参数的使用示例。能够说是对github上使用的很好补充。
smp我也是新手,也没有什么其余心得什么的,就这样吧~~
中小的企业有其自己的局限性,例如优秀的技术人才,有事就会产生一些无奈。切身说法,咱们的web端相关的JS脚本中各个模块从诞生之初就在一个JS文件中,住在一间房子里。通常状况下是没有问题的,可是,多多少少会出现这样的情况:
项目经理:我们这个图片上传模块要改下,后天上线!
前端仔:没问题。由于前端仔成功约到了和女神一块儿看电影,一来兴奋;二来怕加班。其进入仙人模式,歘歘歘三下五除二把JS端的改动都搞定了,就等后台那边对页面修改了!
可是,刚改完不久,悲剧来了——项目经理:赶快,发现一个重大bug, 支付计算貌似有漏洞,赶快fix它,上线!
前端仔:没问题。又进入无敌模式
,快刀斩乱麻,漏洞补上了。结果,准备发布JS上线的时候,前端仔抓狂了
尼玛,不能上啊。图片上传页面还没改,上线了虽然支付没有问题,可是,图片上传被搞残了啊!
因而本来兴奋的前端仔像被艾尼路劈了同样,焉了
。因而,回到苦逼状态,把以前改好的图片上传模块又改回先前的样子……
这就是没有模块化的痛苦。然而,问题早就知道,可是,一直没有去解决,为什么?没人搞这件事。其实,静态资源压缩并合并对于有经验编程人员讲并非难事。看大众点评网,虽然你们都是使用MooTools, 可是,其静态资源就能够压缩合并,可是,咱们这里,没人弄,虽然提过,虽然有人说过愿意作这个事情。我曾研究过淘宝开源的一个JS合并加载工具,可是是PHP的,而咱们用的.net
, 有点折腾不来!因而,就这样拖着~~
不过,如今,貌似能够不用依赖.net
程序员们了,在node环境下,使用seajs模块化书写,spm合并并压缩。先前的一些维护问题显然不复存在。因而,咱们的精力能够更多地放在代码实现以及如何更好地划分模块上,这有助于工做效率的提高。
所以,seajs我是会去使用的,虽然它的做者不是foreigner. 至于文章一开始提到的Jscex, 恩……它能够帮我把到妹子吗?不能!能够帮我钓到大鱼吗?不能!能够帮我车子加油吗?不能!所以,我感受我不会去用它。
扯淡居多,但愿不会浪费您宝贵的时间。感谢阅读,若是表述不许确之处,欢迎指正。
对了,我有问题求教:在弹出框实例页面中,(require, exports, module)
这三个参数惟独module
一次也没有使用,所以,我想问下,module
在何种情境下使用,有何做用?
原创文章,转载请注明来自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=2476