如今的web開發(fā)也需要越來越接近MVC框架模式,web的前端可視為由結構+表現(xiàn)+行為組成,根據(jù)W3C的標準,使用xhtml+css已經(jīng)使得結構和表現(xiàn)成功分離。在網(wǎng)上看到越來越多被重構過的網(wǎng)站是件非常令人欣喜的事情,如果現(xiàn)在要讓我再做一個表格布局的網(wǎng)頁,當我看到那一堆可以被一句CSS代替的表格代碼時,我甚至會惡心到想吐!標準給掙扎在混沌的淤泥里的我們帶來了清新空氣,良好重構過的頁面也像出淤泥而不染的清蓮,香馨沁人心脾!那么下一步就應該是結構和行為的分離了,因為表現(xiàn)和行為本來是不相關的,就算微軟的瀏覽器標準支持一個我當時非常喜歡的css里的behavior,但現(xiàn)在看來表現(xiàn)依然不能包括行為,不應該去代替行為行事。在這個三角形里,結構可以說是重點,表現(xiàn)依賴于結構,行為也依賴于結構,表現(xiàn)和行為的聯(lián)系相對較少(除了一些特效操作),表現(xiàn)是被結構導入的,于是開始思考,行為是否也可以完全由外部導入,在結構即html頁面里完全看不到一句javascript代碼?
經(jīng)過本人一番研究,至少一半左右簡單應用的行為是可以分離開的。為什么說是一半呢,由于通過對對象定義的事件函數(shù)還存在參數(shù)傳遞的一些問題,但繞過這個障礙實施全部應用的可行性正在研究中,而且態(tài)勢也在逐漸明朗,將在下文提及。所以答案是肯定的——結構(html)與行為(javascript)可以實現(xiàn)分離!
下面來看分離面臨的核心問題,一個我的實例(為方便調(diào)試,js代碼仍寫在script標簽里,但其他任何body里的對象都不再添加js代碼):
函數(shù)initBehavior()的作用就是建立一個操作序列,為每個html文檔結構中需要使用行為的對象進行事件觸發(fā)與相應操作處理函數(shù)的連接,即生成行為。如例子中對id為holder的div元素添加的onclick事件函數(shù),同理也可以添加onmouseover,onmouseout……等事件。于是我們分離的第一步完成了,這一步要做的就是重復initBehavior函數(shù)里面的內(nèi)容,添加其他觸發(fā)事件。
接下來要做的就是具體實現(xiàn)每個觸發(fā)函數(shù)了,如上例showNode()函數(shù),問題的核心也就在這里,因為定義的是事件處理入口,函數(shù)中沒辦法在定義事件的時候就確定參數(shù),于是參數(shù)表就隱式被傳遞了。為什么說有參數(shù)表,這也是在查閱了網(wǎng)上一些資料才知道的,每個函數(shù)也是一個對象,函數(shù)對象就有一個屬性是arguments:Array(),而當函數(shù)被調(diào)用時,參數(shù)都是arguments里的元素,這個大家可以另外做測試。要說的是,不同的瀏覽器在這里有一點小小的區(qū)別,對于IE,每當一個事件被觸發(fā)時他的一個全局對象window.event就會接收到信息,在處理函數(shù)的參數(shù)表里并沒有體現(xiàn)。而FF則不同,一個事件觸發(fā)時,則與這個事件連接的處理函數(shù)會帶有一個默認的事件參數(shù),作為參數(shù)表里的第一個參數(shù)傳遞給處理函數(shù),這里參數(shù)表就派上用場了,看上面的程序,由于函數(shù)沒有定義形參,IE解析的參數(shù)表里面是空的,所以函數(shù)里定義的evt得到的是event的引用,F(xiàn)F則因為事件作為第一個參數(shù)表里的元素也得到一個事件對象。下一句也就容易理解了,對于不同瀏覽器,F(xiàn)F的事件來源屬性是target,IE的是srcElement,那么到這里就通過解析得到事件來源對象,也就可以對這個對象進行相關操作了,那么本來需要從函數(shù)傳遞過來的對象參數(shù)也就不必要了。這里說到上面提到的一個不允許傳遞參數(shù)的機制,這個是在flash的ActionScript里也碰到的,仔細思考了一下,似乎明白了設置這個機制的道理,因為當一個事件觸發(fā)函數(shù)時,其實需要傳遞的參數(shù)都是在外部暫時靜態(tài)存在的,那么直接在函數(shù)里調(diào)用外部的對象或其他數(shù)據(jù),也就完成了需求。
說是完成了,但心里總是隱隱約約覺得不妥,好象還是不完美,不過到這已經(jīng)足夠了,我們的目的是結構與行為的分離,那么已經(jīng)實現(xiàn)了,收工大吉!