一年前刚开始做项目的时候,我对于前台技术还刚刚入门,用jquery写点小打小闹的交互效果还是没太大问题,但是要把所有这些效果干净,整洁的部署到全站,对我来说就有点头疼了.由于网站页面虽说不是特别多,但也有二三十个,如果每个页面写一个单独的js文件或者直接把js写在页面内,是不利于维护和有损前台性能的.按照yahoo的前台性能提升建议,应该尽量减少文件个数.于是我决定想办法把除了jquery库及一些插件之外自写代码全部写到一个文件之中.虽然可能有时候某些页面载入的js会有用不到的代码,但是这样做对于一个中等规模的网站来说有如下的性能优势:
这样的部署,可以谓之'轻便'.现在的问题就是,如何组织这个文件,让其尽量有条理. 当然当时的我还是菜鸟,写js的程度还在只会使用jquery的阶段,对于扩展jquery是一无所知,更不用说js闭包,用js模拟其他语言的OOP使用,以及设计模式这些比较专业的技巧了(其实现在对这些技术还在学习当中). 我不可能凭空想出一个好的办法来,所以就开始参考其他性能比较出色的web2.0站的js代码. 国外网站(如digg,netvibes)的js都用packer之类的东西加了密,人读起来很困难,于是又转向国内,看了看校内等,js文件好多,毕竟是大型网站不适合.后来找到豆瓣,发现性能性能相当出色,而且当时的js也没加密,只有三个文件jquery.js,suggest.js以及douban.js.其中最后一个文件是值得参考的.
豆瓣代码研究当时读豆瓣的代码也费了不少劲. 我发现在豆瓣的Html中有些元素的类(class)名称很特别,比如(注意class属性的值)
而且这些元素一般都是有js来增强交互效果的,比如表单元素,推荐按钮等;在douban.js中也存在很多与上述一些元素类名称命名一致的变量,比如
Douban.init_search_text = function(o){
//这里是相关代码
}
于是我就想,豆瓣应该是这样想的:把js当CSS来用,当赋予某些元素特定的类名称时,该元素就会拥有相应的js特性,比如上面说的input元素拥有类名称a_search_text,于是就拥有了Douban.init_search_text这个变量(或者说函数)赋予的js特性.这是怎么实现的呢?为了方便说明,把douban.js简化如下,省略了细致末节,大家可以大致看出主干:
//------第一段------
var Douban = new Object();
Douban.EventMonitor = function(){
this.listeners = new Object();
}
Douban.EventMonitor.prototype.broadcast=function(widgetObj, msg, data){/*代码省略了*/};
Douban.EventMonitor.prototype.subscribe=function(msg, callback){/*代码省略了*/};
Douban.EventMonitor.prototype.unsubscribe=function(msg, callback){/*代码省略了*/};
//------第二段------
var event_monitor = new Douban.EventMonitor();
function load_event_monitor(root) {
var re = /a_(\w+)/;
var fns = {};
$(".j", root).each(function(i) {
var m = re.exec(this.className);
if (m) {
var f = fns[m[1]];
if (!f) {
f = eval("Douban.init_"+m[1]);
fns[m[1]] = f;
}
f && f(this);
}
});
}
$(function() {
load_event_monitor(document);
});
//------第三段------
Douban.init_evc = function(o) {/*...*/};
Douban.init_enb = function(o) {/*...*/};
Douban.init_folder_n = function(o){/*...*/};
Douban.init_unfolder = function(o){/*...*/};
...
可以把代码分为三段:
山寨版的代码以及小技巧读懂豆瓣的代码后,就开始部署自己的山寨版代码,实施方法大致差不多(只不过把Douban对象换成了XM),就不再赘述,文章结尾有demo网址.这里介绍用这种方法的几种技巧.
XM.init_confirm = function(o) {
if(!o.name){
$(o).click(function(){
var text = o.title || $(o).text();
return confirm("确定要"+text+"?");
});
}
使用示例
<a href="/delete" title="删除这个帖子"
class="j x_init_confirm">删除</a>
点击这个链接后会弹出确认框,提示"确定要删除这个帖子吗?",点击确定将前往删除页面,点"取消"可以取消操作
XM.URL = {
user_avatar: '/Content/i/ud.gif',
group_avatar:'/Content/i/gd.gif',
topic_thumb: '/Content/i/tnd.gif'
};
其他技巧会在本系列的后续文章中穿插提到. 大家有什么疑问和建议,欢迎评论,希望共同提高!
douban.js在这里: 下载