開頭引用一段 想起一句話:前端研究,研究個屁~ 的確如此呀。補充下聯:前端設計,設計個屁~ 前端目前最大的困境是,如 HTML 一樣,無論你承不承認,市場上並不太需要 HTML 高手其實這裡引發一個問題:前端的價值究竟是什嗎?未來應該如何發展? 我個人覺得還是一個核心價值的問題,前端在漂亮的東西都是需要後端的資料支撐的,而且前端的絕大部分問題,其實都需要後端才能解決,就如我開發了三年的混合項目,雖然前端代碼有3萬行,但是後端一個資料拷貝失敗,整個項目都是白搭 當然這裡我並非要深入這個話題,只是想表明儘可能的提高自身的價值! 從前端的曆史變更與發展過程來看,如果拿人類的曆史來比喻,從最原始的刀耕火種以HTML靜態結構為主的原始社會,到後來帶有邏輯處理與伺服器混搭互動的的石器時代以及最近幾年流行的node.js,MVC,MVVM,Phonegap等衍生而來的東東讓前端大躍進式的跳躍進入了一個新的工業時代,不到20年的時間web技術翻天覆地的變化 如今的前端進入了 MV* 時代,同時Ajax也帶來了SPA,Node帶來了全棧,這些都切實推動著前端往前發展 優秀的前端一方面是完成的效率,另一方面是可維護和可擴充性的提高帶來的潛在價值,解放生產力,專註展現與商務邏輯,減少瑣碎的相容處理 如果你使用一面大鏡子作為衝浪板會發生什麼?或許你會在較短的時間內征服海浪,但是你肯定從內心深處明白,這不是衝浪的正確選擇 所以我們不應該只要求自己僅僅停留在API的層次,如果能理解原理深入設計,那麼就將會跨上一個新的台階 jQuery.Ajax做了那些事? 我們知道AJAX的底層實現其實是很簡單的.拋開IE不說,標準的w3c直接提供了XMLHttpRequest方法 關於AJAX基礎請飛機 觸碰jQuery:AJAX非同步詳解 我們主要站在設計的角度理解,如何設計出低耦合高內聚的代碼 jQuery對Ajax的處理主要體現在對瀏覽器安全色,資料的處理及過濾,各種事件的封裝上 主要有以下幾部分擴充: 提供快捷介面 提供底層介面 提供資料序列化 提供全域Ajax事件處理 具體使用請看API,這裡不再重複 分析下面一個demo 給document綁定ajaxStart,ajaxComplete回調事件 trigger綁定一個點擊事件,發送ajax請求 點擊trigger出發點之後,發送一個ajax請求,並且通過complete,done,ajaxStart, ajaxComplete返回狀態回調 //全域事件觸發$(document).ajaxStart(function() { console.log(arguments)}).ajaxComplete(function() { $(".log").text("Triggered ajaxComplete handler.");}); $(".trigger").click(function() { //發送ajax請求 // $.ajax({ url: "php.html", context: document.body, complete: function() { console.log(this) } }).done(function() { console.log(this) });}); 這裡實現比較特別的地方 針對ajax提供2種回調方式,內部的complete回調與外部的done回調 全域document上都能捕獲到ajax的每一步的回調通知 換句話說,針對ajax的請求,每一步的狀態,成功或者失敗,我們有3種方式可以擷取,但是每一種還是有各自的區別 1 ajax的參數回調 2 基於deferred方式的done回調 3 全域的的自訂事件的回調 從設計的層面上來考下,這種事件組合的方式是如何??有什麼優勢? 設計一: tAjax({ url: "php.html", complete: function(data) { console.log(data) }})如果要實現這種介面調用 那麼我們就需要封裝下代碼,把回調通過實參傳遞 var tAjax = function(config) { var url = config.url; var complete = config.complete; var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); xhr.open('post', url); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status == 200) { complete(xhr.responseText); } } } xhr.send();} 這樣設計可以看做類似原廠模式的封裝,好處不用多說,在原廠模式裡麵包含了對象的建立等必要的邏輯,用戶端根據傳參選擇動態執行個體化相對的處理 對於用戶端來去除了具體的依賴,當然tAjax你也可以看作一個面板模式提供的介面,其實就是隱藏了具體的複雜邏輯,提供一個簡單的介面,從而降低耦合 設計二: tAjax({ url: "php.html", complete: function(data) { console.log(data) }}).done(function(data){ console.log(data)}) 在之前加入了一個done鏈式處理,當然這裡done,其實是deferred的一個成功處理通知,如果之前沒有接觸,大家去瞭解一下關於deferred的概念 我們知道jQuery實現了鏈式,實現的原理無法就是返回本身對象的引用 var ajax = tAjax({ url: "php.html", complete: function(data) { console.log(data) }}) ajax.done(function(){ }) 以上是分離的情況下,如果要合并成一條鏈式處理,只要在上一個方法中返回this即可 所以我們改改 var tAjax = function(config) { var doneFn; var url = config.url; var complete = config.complete; var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); xhr.open('post', url); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status == 200) { doneFn(xhr.responseText); complete(xhr.responseText); } } } xhr.send(xhr.responseText); return { /** * 返回一個done對象 */ done: function(ourfn) { doneFn = ourfn; } };} 我們返回了一個done對象,這裡一樣要是對象,因為鏈式的原因,我們看外部指定了內部的done,從而把外部函數給引用到內部的doneFn上 緩衝起來 xhr.staturs 成功後一起執行 當然這種設計是有問題的,如果在done之後我在鏈式就肯定不行,因為對象的引用錯了,那麼jQuery是如何處理? 設計三 提供document對象的全域處理 $(document).ajaxComplete(function() { console.log('ajax請求成功')}); tAjax({ url: "php.html", complete: function(data) { console.log(data) }}).done(function(data){ console.log(data)}) 這裡的問題就是把ajax內部的事件,返回給全域捕獲了,有點類似css3的全域動畫事件 這裡的設計其實最簡單了因為本身之間沒有什麼耦合,就是發送一個事件給document即可 jQuery利用了trigger自訂事件觸發的 globalEventContext.trigger("ajaxComplete", [jqXHR, s]);具體每一種實現在後面的都會提到,在這裡需要大家有個整體的印象, 總結: 通過讀閱jQuery.ajax這段api我們可以看到jQuery對ajax的處理做的相當的全面 首先我們經常遇到某些耗時很長的javascript操作。其中,既有非同步操作(比如ajax讀取伺服器資料),也有同步的操作(比如遍曆一個大型數組),它們都不是立即能得到結果的。 通常的做法是,為它們指定回呼函數(callback)。即事先規定,一旦它們運行結束,應該調用哪些函數。 ajax引入了deferred方案,callback方案就是回呼函數解決方案,從而處理耗時操作的問題,對那些操作提供了更好的控制,以及統一的編程介面 伴隨Ajax請求會觸發若干事件,我們可以訂閱這些事件並在其中處理我們的邏輯。 在jQuery中有兩種Ajax事件:局部事件和全域事件。 局部事件(回呼函數),在$.ajax()方法的options參數中聲明,可以用來佈建要求資料和擷取、處理響應資料。 全域事件,每次Ajax請求都會觸發,它會向DOM中的所有元素廣播,你只需為DOM中任意元素bind好全域事件即會觸發(若綁定多次,則會依次觸發為事件註冊的回呼函數