Douban是2.0 社区里面比较成功的一个产品, 里面ajax技术也做得不错, 把它的源码拿来研究了一下, 它在页面上使用了jquery,  我比较喜欢它的一体式的事件处理机制,不用写很多的事件绑定代码,只需要通过一定的命名规则就可以自动给页面元素加上一些功能, 它上面几乎所有的功能都通过这个实现, 配合jquery强大的选择器,代码看起来比较简洁清晰.  下面我们就来看看它的一些核心部分. 我使用的是jquery 1.2.3,压缩之后29kb大小, 速度感觉上比以前有比较大的改善.废话不多说了,直接看看代码吧. 另外推荐一下blueprint 这个css框架,还挺好用的. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//定义命名空间 ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
var Bowtech=new Object(); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//注册全局的事件监视器. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
Bowtech.EventMonitor = function(){ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
this.listeners = new Object(); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
}
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//广播事件 ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
Bowtech.EventMonitor.prototype.broadcast=function(widgetObj, msg, data){ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
var lst = this.listeners[msg]; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
if(lst != null){ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
       
for(var o in lst){ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
            lst[o](widgetObj, data); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
        }
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    }
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
}
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//绑定所有的事件. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
Bowtech.EventMonitor.prototype.subscribe=function(msg, callback){ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
var lst = this.listeners[msg]; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
if (lst){ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
        lst.push(callback); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    }
else{ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
       
this.listeners[msg] = [callback]; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    }
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
}
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//取消事件绑定. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
Bowtech.EventMonitor.prototype.unsubscribe=function(msg, callback){ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
var lst = this.listener[msg]; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
if (lst != null){ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
        lst
= lst.filter(function(ele, index, arr) {return ele!=callback;}); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    }
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
}
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
// Page scope event-monitor obj. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
var event_monitor = new Bowtech.EventMonitor(); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//对于所有 class="j a_xxx yyy" id="xxx-123"的元素执行事件绑定, xxx-123部分用来获取元素的ID,比如一个帖子的ID, ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//
a_xxx  后面的部 ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//
分用来标识应用如 vote / review / blog 等. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//
绑定的事件就是 :  Bowtech.init_vote / Bowtech.init_blog 等. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
function load_event_monitor(root) { ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
var re = /a_(\w+)/; //正则表达式获取ID. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
var fns = {}; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    $(
".j", root).each(function(i) { ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
       
var m = re.exec(this.className); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
       
if (m) { ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
           
var f = fns[m[1]]; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
           
if (!f) { //如果事件处理函数不存在则创建函数对象. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                f = eval("Bowtech.init_"+m[1]); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                fns[m[
1]] = f;//调用绑定函数. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
            } ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
            f
&& f(this); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
        }
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    }
); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
}
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//在文档加载完毕后将执行的方法(参见jquery文档) ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//
一般来说文档加载的时候应该绑定所有的事件, 但是有一种情况例外. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//
比如 通过Ajax方法取回来的内容里面还含有动作按钮的,这时需要针对这部分功能执行绑定. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//
需要手动调用 load_event_monitor(element);  方法. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
$(function() { ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    load_event_monitor(document); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
}
); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//注意这里的o对象是一个html 元素而非是一个jquery对象,所以在调用它的方法时应该使用$(o)函数 ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
//
把它转化为jquery对象. ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
Bowtech.init_forder = function(o) { ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
var eid = $(o).attr("id").split("-")[1]; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
var fo = $("#f-"+eid); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
   
var unfo = $("#unf-"+eid); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    fo.click(
function() { ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
      $(o).hide(); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
      unfo.show(); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
      fo.hide(); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    }
); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    unfo.click(
function() { ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
        $(o).show(); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
        fo.show(); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
        unfo.hide(); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    }
); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
}
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
jQuery.fn.extend(
{ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    set_caret:
function(){ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
       
if(!$.browser.msie) return; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
       
var initSetCaret = function() {this.caretPos = document.selection.createRange().duplicate()}; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
       
this.click(initSetCaret).select(initSetCaret).keyup(initSetCaret); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    }
, ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    insert_caret:
function(textFeildValue) { ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
       
var textObj = this[0]; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
       
if(document.all && textObj.createTextRange && textObj.caretPos) { ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
           
var caretPos=textObj.caretPos; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
            caretPos.text
= caretPos.text.charAt(caretPos.text.length-1) == '' ? textFeildValue+'' : textFeildValue; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
        }
else if(textObj.setSelectionRange) { ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
           
var rangeStart=textObj.selectionStart; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
           
var rangeEnd=textObj.selectionEnd; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
           
var tempStr1=textObj.value.substring(0,rangeStart); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
           
var tempStr2=textObj.value.substring(rangeEnd); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
            textObj.value
=tempStr1+textFeildValue+tempStr2; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
            textObj.focus(); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
           
var len=textFeildValue.length; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
            textObj.setSelectionRange(rangeStart
+len,rangeStart+len); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
            textObj.blur(); ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
        }
else{ ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
            textObj.value
+=textFeildValue; ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
        }
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
    }
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
}
)
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
前台要用就比较简单了,  只需要这样写: ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
<div id="test2" class="mod"> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
               
<h3> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                    这里可以放标题 ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
               
</h3> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
               
<div class="j modb a_forder" id="modb-1002"> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                    这里是一些主要的内容 ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                   
<dl> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                       
<dt>Hello world</dt> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                       
<dd> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                            hahaha
</dd> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                   
</dl> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                    这个实验在沙加的神舟本上完成 ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
               
</div> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
               
<div class="edit"> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                   
<a id="f-1002" class="forder" href="javascript:void(0);">[收起]</a> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
<a id="unf-1002" ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
                        class
="unforder" href="javascript:void(0);">[展开]</a> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
               
</div> ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
           
</div>
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
样式就省略了, 大家可以自己写, 最后发两个效果图: ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
收起时的样子 ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P
开发环境:  沙加的神舟本, VS2008, Framework 2.0 ²´% þ¡ºçwww.netcsharp.cnJ Ö*,ŠÄ½P