摘要:對(duì)象待會(huì)講,我認(rèn)為是設(shè)計(jì)最巧妙的地方。在跨域的時(shí)候會(huì)使用到,這是為了禁止使用。的目的在于創(chuàng)建一個(gè)事件,然后在觸發(fā)他,如果默認(rèn)行為被取消了,則返回。這是的初始化,默認(rèn)是請(qǐng)求,是新建的對(duì)象,表示瀏覽器是否應(yīng)該被允許緩存響應(yīng)。
在學(xué)習(xí)zepto的源碼的時(shí)候,不得不稱贊這些人的厲害,我雖然能看明白,但是要我寫,估計(jì)吭哧吭哧寫不出來。雖然現(xiàn)在很少人使用zepto了,但是學(xué)習(xí)這些源碼我相信每次看都能給咱們不同的感受。Deferred對(duì)象待會(huì)講,deferred我認(rèn)為是zepto設(shè)計(jì)最巧妙的地方。先來看zepto的ajax模塊。
;(function($){ var jsonpID = +new Date(); function triggerAndReturn(context, eventName, data) { var event = $.Event(eventName); $(context).trigger(event, data); return !event.isDefaultPrevented(); } })
這里為什么文件開頭都要使用";"這是因?yàn)樵趯?duì)多個(gè)js文件進(jìn)行打包的時(shí)候,如果使用換行分隔代碼,當(dāng)合并壓縮多個(gè)文件之后,換行符會(huì)被刪掉,連在一起可能出錯(cuò),加上分號(hào)就保險(xiǎn)了。
jsonpID在跨域jsonp的時(shí)候會(huì)使用到,這是為了禁止使用cache。triggerAndReturn()的目的在于創(chuàng)建一個(gè)Event事件,然后在context觸發(fā)他,如果默認(rèn)行為被取消了,則返回false。
$.ajaxSettings = { type: "GET", success: empty, xhr: function () { return new window.XMLHttpRequest() }, cache: true, crossDomain: false }
這是ajax的初始化,默認(rèn)是GET請(qǐng)求,xhr是新建的XMLHttpRequest()對(duì)象,cache表示瀏覽器是否應(yīng)該被允許緩存GET響應(yīng)。crossDomain表示是否可以來自另外一個(gè)域。
下面來看看最核心的$.ajax方法。
$.ajax = function (options) { var settings = $.extend({}, options || {}), deferred = $.Deferred && $.Deferred(), urlAnchor, hashIndex for (key in $.ajaxSettings) if (settings[key] === undefined) settings[key] = $.ajaxSettings[key] ajaxStart(settings) ... }
首先傳入options,然后將傳入的options存儲(chǔ)到本地,deferred咱們暫時(shí)可以把它看成一個(gè)promise對(duì)象,遍歷$.ajaxSettings,如果用戶沒有設(shè)置里邊有的屬性,那就使用默認(rèn)的屬性。然后調(diào)用ajaxStart開始的函數(shù)。
if (!settings.crossDomain) { urlAnchor = document.createElement("a"); urlAnchor.href = settings.url; urlAnchor.href = urlAnchor.href; settings.crossDomain = (originAnchor.protocol + "http://" + originAnchor.host) !== (urlAnchor.protocol + "http://" + urlAnchor.host) }
這里首先crossDomain為false的情況下,進(jìn)入該邏輯,通過判斷我們傳入的url和當(dāng)前window.location.href做對(duì)比,判斷是不是跨域。
if ((hashIndex = settings.url.indexOf("#")) > -1) settings.url = settings.url.slice(0, hashIndex) var dataType = settings.dataType, hasPlaceholder = /?.+=?/.test(settings.url); if (hasPlaceholder) dataType = "jsonp"; if (settings.cache === false || ( (!options || options.cache !== true) && ("script" == dataType || "jsonp" == dataType) )) settings.url = appendQuery(settings.url, "_=" + Date.now()) function appendQuery(url, query) { if (query == "") return url; return (url + "&" + query).replace(/[&?]{1,2}/, "?") } if ("jsonp" == dataType) { if (!hasPlaceholder) settings.url = appendQuery(settings.url, settings.jsonp ? (settings.jsonp + "=?") : settings.jsonp === false ? "" : "callback=?") return $.ajaxJSONP(settings, deferred) }
如果我們沒有傳入url,那么url就是window.location.href。"#"代表網(wǎng)頁(yè)中的一個(gè)位置,右邊的字符,就是該位置的標(biāo)識(shí)符,#是用來指導(dǎo)瀏覽器動(dòng)作的,對(duì)瀏覽器沒有用,所以在截取url的時(shí)候,沒必要把后面的部分傳給服務(wù)器。hasPlaceholder這里的正則表達(dá)式,用于匹配類似"?name=?"這種字符串,如果hasPlaceholder為true,則dataType為jsonp。下面的時(shí)不使用留在緩存的數(shù)據(jù),第一種是設(shè)置cache為false,或者dataType為script和jsonp的情況,需要在url后面添加事件。下面是appendQuery方法,就是把字符串拼接到url后邊,但是需要把"&"替換成"?"。如果我們的請(qǐng)求是jsonp請(qǐng)求,需要在url后面添加一些callback=?這種參數(shù)。
var mime = settings.accepts[dataType], headers = {}, setHeader = function(name, value) {headers[name.toLowerCase()] = [name, value]}, protocol = /^([w-]+:)///.test(settings.url) ? RegExp.$1 : window.location.protocol, xhr = settings.xhr(), nativeSetHeader = xhr.setRequestHeader, abortTimeout if (deferred) deferred.promise(xhr); if (!settings.crossDomain) setHeader("X-Requested-With", "XMLHttpRequest"); setHeader("Accept", mime || "*/*") if (mime = settings.mimeType || mime) { if (mime.indexOf(",") > -1) mime = mime.split(",", 2)[0] xhr.overrideMimeType && xhr.overrideMimeType(mime) }
settings中的accepts表示從服務(wù)器請(qǐng)求的MIME類型,指定dataType的值,包括script、json、xml、html、text。mime存儲(chǔ)的就是類似"application/json"的字符串。protocol就是匹配咱們類似"http://"的這種協(xié)議。
如果deferred存在,就把xhr轉(zhuǎn)換為deferred對(duì)象。接著看下去,如果不是跨域的,那就是ajax請(qǐng)求。然后后面的判斷條件查了一下是針對(duì)一些mozillar瀏覽器進(jìn)行修正(有個(gè)問題就是他們上哪兒知道的用這種方式來修正啊)。
xhr.onreadystatechange = function() { if (xhr.readyState == 4) { xhr.onreadystatechange = empty if (/*如果成功*/){ // 對(duì)返回結(jié)果進(jìn)行處理 } } } xhr.open(settings.type, settings.url, async, settings.username, settings.password)
沒什么難的,就是根據(jù)傳入的參數(shù)不同進(jìn)行處理。
$.param這個(gè)函數(shù)的作用在于序列化傳入對(duì)象,下面是他的代碼:
$.param = function (obj, traditional) { var params = [] params.add = function (key, value) { if ($.isFunction(value)) value = value() if (value == null) value = "" this.push(escape(key) + "=" + escape(value)) } serialize(params, obj, traditional) return params.join("&").replace(/%20/g, "+") }
傳入一個(gè)對(duì)象,和一個(gè)標(biāo)記,這個(gè)traditional表示激活傳統(tǒng)的方式通過$.param來得到data。首先定義一個(gè)空數(shù)組,如果在上面添加方法,這個(gè)方法的主要作用向params里邊添加序列化的對(duì)象,escape=encodeURIComponent,然后調(diào)用serialize,將obj對(duì)象添加到params中,最后返回將params數(shù)組用"&"拼接,然后這里的%20表示空格,意思是將空格替換成"+"
serialize下面是代碼
function serialize(params, obj, traditional, scope) { var type, array = $.isArray(obj), hash = $.isPlainObject(obj) $.each(obj, function (key, value) { type = $.type(value) if (scope) key = traditional ? scope : scope + "[" + (hash || type == "object" || type == "array" ? key : "") + "]" // handle data in serializeArray() format if (!scope && array) params.add(value.name, value.value) // recurse into nested objects else if (type == "array" || (!traditional && type == "object")) serialize(params, value, traditional, key) else params.add(key, value) }) }
params是帶有add方法的數(shù)組,遍歷obj的鍵值對(duì),屬性值可能是對(duì)象也可能是數(shù)組或者字符串分別進(jìn)行處理。如果obj的某個(gè)屬性值是對(duì)象或者數(shù)組,scope就代表是該屬性,那么這時(shí)候向params傳入的key就需要變化,變成類似"a[b]"這里的b是obj的某個(gè)屬性值是對(duì)象的一個(gè)屬性。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96676.html
摘要:私有變量用來臨時(shí)存放配置中的,即請(qǐng)求成功后執(zhí)行的回調(diào)函數(shù)名,該配置可以為類型。是根據(jù)配置得出的回調(diào)函數(shù)名。接下來,將的占位符,替換成回調(diào)函數(shù)名,最后將插入到頁(yè)面中,發(fā)送請(qǐng)求。 Ajax 模塊也是經(jīng)常會(huì)用到的模塊,Ajax 模塊中包含了 jsonp 的現(xiàn)實(shí),和 XMLHttpRequest 的封裝。 讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡迎star: reading-...
摘要:讀源碼系列文章已經(jīng)放到了上,歡迎源碼版本本文閱讀的源碼為改寫原有的方法模塊改寫了以上這些方法,這些方法在調(diào)用的時(shí)候,會(huì)為返回的結(jié)果添加的屬性,用來保存原來的集合。方法的分析可以看讀源碼之模塊。 Stack 模塊為 Zepto 添加了 addSelf 和 end 方法。 讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡迎star: reading-zepto 源碼版本 本文閱讀的...
摘要:形如源代碼在的原型上添加了相關(guān)方法。類似源代碼每個(gè)表單的和都通過編碼最后通過符號(hào)分割有了的基礎(chǔ),就是將相應(yīng)的和都通過編碼,然后用符號(hào)進(jìn)行分割,也就達(dá)到了我們要的結(jié)果。 前言 JavaScript最初的一個(gè)應(yīng)用場(chǎng)景就是分擔(dān)服務(wù)器處理表單的責(zé)任,打破處處依賴服務(wù)器的局面,這篇文章主要介紹zepto中form模塊關(guān)于表單處理的幾個(gè)方法,serialize、serializeArray、sub...
摘要:模塊是為解決移動(dòng)版加載圖片過大過多時(shí)崩潰的問題。因?yàn)闆]有處理過這樣的場(chǎng)景,所以這部分的代碼解釋不會(huì)太多,為了說明這個(gè)問題,我翻譯了這篇文章作為附文怎樣處理移動(dòng)端對(duì)圖片資源的限制,更詳細(xì)地解釋了這個(gè)模塊的應(yīng)用場(chǎng)景。 assets 模塊是為解決 Safari 移動(dòng)版加載圖片過大過多時(shí)崩潰的問題。因?yàn)闆]有處理過這樣的場(chǎng)景,所以這部分的代碼解釋不會(huì)太多,為了說明這個(gè)問題,我翻譯了《How to...
閱讀 2846·2023-04-25 22:15
閱讀 1870·2021-11-19 09:40
閱讀 2217·2021-09-30 09:48
閱讀 3298·2021-09-03 10:36
閱讀 2104·2021-08-30 09:48
閱讀 1933·2021-08-24 10:00
閱讀 2772·2019-08-30 15:54
閱讀 753·2019-08-30 15:54