摘要:為什么要用嚴(yán)格等來(lái)作為判斷呢這個(gè)我也不太明白,因?yàn)樵讷@取值時(shí),方法對(duì)不存在的屬性返回值為,用判斷會(huì)不會(huì)更好點(diǎn)呢這樣根本不需要再走方法。
這篇依然是跟 dom 相關(guān)的方法,側(cè)重點(diǎn)是操作屬性的方法。
讀Zepto源碼系列文章已經(jīng)放到了github上,歡迎star: reading-zepto
源碼版本本文閱讀的源碼為 zepto1.2.0
內(nèi)部方法 setAttributefunction setAttribute(node, name, value) { value == null ? node.removeAttribute(name) : node.setAttribute(name, value) }
如果屬性值 value 存在,則調(diào)用元素的原生方法 setAttribute 設(shè)置對(duì)應(yīng)元素的指定屬性值,否則調(diào)用 removeAttribute 刪除指定的屬性。
deserializeValue// "true" => true // "false" => false // "null" => null // "42" => 42 // "42.5" => 42.5 // "08" => "08" // JSON => parse if valid // String => self function deserializeValue(value) { try { return value ? value == "true" || (value == "false" ? false : value == "null" ? null : +value + "" == value ? +value : /^[[{]/.test(value) ? $.parseJSON(value) : value) : value } catch (e) { return value } }
函數(shù)的主體又是個(gè)很復(fù)雜的三元表達(dá)式,但是函數(shù)要做什么事情,注釋已經(jīng)寫得很明白了。
try catch 保證出錯(cuò)的情況下依然可以將原值返回。
先將這個(gè)復(fù)雜的三元表達(dá)式拆解下:
value ? 相當(dāng)復(fù)雜的表達(dá)式返回的值 : value
值存在時(shí),就進(jìn)行相當(dāng)復(fù)雜的三元表達(dá)式運(yùn)算,否則返回原值。
再來(lái)看看 value === "true" 時(shí)的運(yùn)算
value == "true" || (復(fù)雜表達(dá)式求出的值)
這其實(shí)是一個(gè)或操作,當(dāng) value === "true" 時(shí)就不執(zhí)行后面的表達(dá)式,直接將 value === "true" 的值返回,也就是返回 true
再來(lái)看 value === false 時(shí)的求值
value == "false" ? false : (其他表達(dá)式求出來(lái)的值)
很明顯,value === "false" 時(shí),返回的值為 false
value == "null" ? null : (其他表達(dá)式求出來(lái)的值)
為 value == "null" 時(shí), 返回值為 null
再來(lái)看看數(shù)字字符串的判斷:
+value + "" == value ? +value : (其他表達(dá)式求出來(lái)的值)
這個(gè)判斷相當(dāng)有意思。
+value 將 value 隱式轉(zhuǎn)換成數(shù)字類型,"42" 轉(zhuǎn)換成 42 ,"08" 轉(zhuǎn)換成 8 ,abc 會(huì)轉(zhuǎn)換成 NaN 。+ "" 是將轉(zhuǎn)換成數(shù)字后的值再轉(zhuǎn)換成字符串。然后再用 == 和原值比較。這里要注意,用的是 == ,不是 === 。左邊表達(dá)式不用說(shuō),肯定是字符串類型,右邊的如果為字符串類型,并且和左邊的值相等,那表示 value 為數(shù)字字符串,可以用 +value 直接轉(zhuǎn)換成數(shù)字。 但是以 0 開(kāi)頭的數(shù)字字符串如 "08" ,經(jīng)過(guò)左邊的轉(zhuǎn)換后變成 "8",兩個(gè)字符串不相等,繼續(xù)執(zhí)行后面的邏輯。
如果 value 為數(shù)字,則左邊的字符串會(huì)再次轉(zhuǎn)換成數(shù)字后再和 value 進(jìn)行比較,左邊轉(zhuǎn)換成數(shù)字后肯定為 value 本身,因此表達(dá)式成立,返回一樣的數(shù)字。
/^[[{]/.test(value) ? $.parseJSON(value) : value
這長(zhǎng)長(zhǎng)的三元表達(dá)式終于被剝得只剩下內(nèi)衣了。
/^[[{]/ 這個(gè)正則是檢測(cè) value 是否以 [ 或者 { 開(kāi)頭,如果是,則將其作為對(duì)象或者數(shù)組,執(zhí)行 $.parseJSON 方法反序列化,否則按原值返回。
其實(shí),這個(gè)正則不太嚴(yán)謹(jǐn)?shù)?,以這兩個(gè)符號(hào)開(kāi)頭的字符串,可能根本不是對(duì)象或者數(shù)組格式的,序列化可能會(huì)出錯(cuò),這就是一開(kāi)始提到的 try catch 所負(fù)責(zé)的事了。
.html()html: function(html) { return 0 in arguments ? this.each(function(idx) { var originHtml = this.innerHTML $(this).empty().append(funcArg(this, html, idx, originHtml)) }) : (0 in this ? this[0].innerHTML : null) },
html 方法既可以設(shè)置值,也可以獲取值,參數(shù) html 既可以是固定值,也可以是函數(shù)。
html 方法的主體是一個(gè)三元表達(dá)式, 0 in arguments 用來(lái)判斷方法是否帶參數(shù),如果不帶參數(shù),則獲取值,否則,設(shè)置值。
(0 in this ? this[0].innerHTML : null)
先來(lái)看看獲取值,0 in this 是判斷集合是否為空,如果為空,則返回 null ,否則,返回的是集合第一個(gè)元素的 innerHTML 屬性值。
this.each(function(idx) { var originHtml = this.innerHTML $(this).empty().append(funcArg(this, html, idx, originHtml)) })
知道值怎樣獲取后,設(shè)置也就簡(jiǎn)單了,要注意一點(diǎn)的是,設(shè)置值的時(shí)候,集合中每個(gè)元素的 innerHTML 值都被設(shè)置為給定的值。
由于參數(shù) html 可以是固定值或者函數(shù),所以先調(diào)用內(nèi)部函數(shù) funcArg 來(lái)對(duì)參數(shù)進(jìn)行處理,funcArg 的分析請(qǐng)看 《讀Zepto源碼之樣式操作》 。
設(shè)置的邏輯也很簡(jiǎn)單,先將當(dāng)前元素的內(nèi)容清空,調(diào)用的是 empty 方法,然后再調(diào)用 append 方法,插入給定的值到當(dāng)前元素中。append 方法的分析請(qǐng)看《讀Zepto源碼之操作DOM》
.text()text: function(text) { return 0 in arguments ? this.each(function(idx) { var newText = funcArg(this, text, idx, this.textContent) this.textContent = newText == null ? "" : "" + newText }) : (0 in this ? this.pluck("textContent").join("") : null) },
text 方法用于獲取或設(shè)置元素的 textContent 屬性。
先看不傳參的情況:
(0 in this ? this.pluck("textContent").join("") : null)
調(diào)用 pluck 方法獲取每個(gè)元素的 textContent 屬性,并且將結(jié)果集合并成字符串。關(guān)于 textContent 和 innerText 的區(qū)別,MDN上說(shuō)得很清楚:
textContent 會(huì)獲取所有元素的文本,包括 script 和 style 的元素
innerText 不會(huì)將隱藏元素的文本返回
innerText 元素遇到 style 時(shí),會(huì)重繪
具體參考 MDN:Node.textContent
設(shè)置值的邏輯中 html 方法差不多,但是在 newText == null 時(shí),賦值為 "" ,否則,轉(zhuǎn)換成字符串。這個(gè)轉(zhuǎn)換我有點(diǎn)不太明白, 賦值給 textContent 時(shí),會(huì)自動(dòng)轉(zhuǎn)換成字符串,為什么要自己轉(zhuǎn)換一次呢?還有,textContent 直接賦值為 null 或者 undefined ,也會(huì)自動(dòng)轉(zhuǎn)換為 "" ,為什么還要自己轉(zhuǎn)換一次呢?
.attr()attr: function(name, value) { var result return (typeof name == "string" && !(1 in arguments)) ? (0 in this && this[0].nodeType == 1 && (result = this[0].getAttribute(name)) != null ? result : undefined) : this.each(function(idx) { if (this.nodeType !== 1) return if (isObject(name)) for (key in name) setAttribute(this, key, name[key]) else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name))) }) },
attr 用于獲取或設(shè)置元素的屬性值。name 參數(shù)可以為 object ,用于設(shè)置多組屬性值。
判斷條件:
typeof name == "string" && !(1 in arguments)
參數(shù) name 為字符串,排除掉 name 為 object 的情況,并且第二個(gè)參數(shù)不存在,在這種情況下,為獲取值。
(0 in this && this[0].nodeType == 1 && (result = this[0].getAttribute(name)) != null ? result : undefined)
獲取屬性時(shí),要滿足幾個(gè)條件:
集合不為空
集合的第一個(gè)元素的 nodeType 為 ELEMENT_NODE
然后調(diào)用元素的原生方法 getAttribute 方法來(lái)獲取第一個(gè)元素對(duì)應(yīng)的屬性值,如果屬性值 !=null ,則返回獲取到的屬性值,否則返回 undefined 。
再來(lái)看設(shè)置值的情況:
this.each(function(idx) { if (this.nodeType !== 1) return if (isObject(name)) for (key in name) setAttribute(this, key, name[key]) else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name))) })
如果元素的 nodeType 不為 ELEMENT_NODE 時(shí),直接 return
當(dāng) name 為 object 時(shí),遍歷對(duì)象,設(shè)置對(duì)應(yīng)的屬性
否則,設(shè)置給定屬性的值。
.removeAttr()removeAttr: function(name) { return this.each(function() { this.nodeType === 1 && name.split(" ").forEach(function(attribute) { setAttribute(this, attribute) }, this) }) },
刪除給定的屬性。可以用空格分隔多個(gè)屬性。
調(diào)用的其實(shí)是 setAttribute 方法,只將元素和需要?jiǎng)h除的屬性傳遞進(jìn)去, setAttribute 就會(huì)將對(duì)應(yīng)的元素屬性刪除。
.prop()propMap = { "tabindex": "tabIndex", "readonly": "readOnly", "for": "htmlFor", "class": "className", "maxlength": "maxLength", "cellspacing": "cellSpacing", "cellpadding": "cellPadding", "rowspan": "rowSpan", "colspan": "colSpan", "usemap": "useMap", "frameborder": "frameBorder", "contenteditable": "contentEditable" } prop: function(name, value) { name = propMap[name] || name return (1 in arguments) ? this.each(function(idx) { this[name] = funcArg(this, value, idx, this[name]) }) : (this[0] && this[0][name]) },
prop 也是給元素設(shè)置或獲取屬性,但是跟 attr 不同的是, prop 設(shè)置的是元素本身固有的屬性,attr 用來(lái)設(shè)置自定義的屬性(也可以設(shè)置固有的屬性)。
propMap 是將一些特殊的屬性做一次映射。
prop 取值和設(shè)置值的時(shí)候,都是直接操作元素對(duì)象上的屬性,不需要調(diào)用如 setAttribute 的方法。
.removeProp()removeProp: function(name) { name = propMap[name] || name return this.each(function() { delete this[name] }) },
刪除元素固定屬性,調(diào)用對(duì)象的 delete 方法就可以了。
.data()capitalRE = /([A-Z])/g data: function(name, value) { var attrName = "data-" + name.replace(capitalRE, "-$1").toLowerCase() var data = (1 in arguments) ? this.attr(attrName, value) : this.attr(attrName) return data !== null ? deserializeValue(data) : undefined },
data 內(nèi)部調(diào)用的是 attr 方法,但是給屬性名加上了 data- 前綴,這也是向規(guī)范靠攏。
name.replace(capitalRE, "-$1").toLowerCase()
稍微解釋下這個(gè)正則,capitalRE 匹配的是大寫字母,replace(capitalRE, "-$1") 是在大寫字母前面加上 - 連字符。這整個(gè)表達(dá)式其實(shí)就是將 name 轉(zhuǎn)換成 data-camel-case 的形式。
return data !== null ? deserializeValue(data) : undefined
如果 data 不嚴(yán)格為 null 時(shí),調(diào)用 deserializeValue 序列化后返回,否則返回 undefined 。為什么要用嚴(yán)格等 null 來(lái)作為判斷呢?這個(gè)我也不太明白,因?yàn)樵讷@取值時(shí),attr 方法對(duì)不存在的屬性返回值為 undefined ,用 !== undefined 判斷會(huì)不會(huì)更好點(diǎn)呢?這樣 undefined 根本不需要再走 deserializeValue 方法。
.val()val: function(value) { if (0 in arguments) { if (value == null) value = "" return this.each(function(idx) { this.value = funcArg(this, value, idx, this.value) }) } else { return this[0] && (this[0].multiple ? $(this[0]).find("option").filter(function() { return this.selected }).pluck("value") : this[0].value) } },
獲取或設(shè)置表單元素的 value 值。
如果傳參,還是慣常的套路,設(shè)置的是元素的 value 屬性。
否則,獲取值,看看獲取值的邏輯:
return this[0] && (this[0].multiple ? $(this[0]).find("option").filter(function() { return this.selected }).pluck("value") : this[0].value)
this[0].multiple 判斷是否為下拉列表多選,如果是,則找出所有選中的 option ,獲取選中的 option 的 value 值返回。這里用到 pluck 方法來(lái)獲取屬性,具體的分析見(jiàn):《讀Zepto源碼之集合元素查找》
否則,直接返回第一個(gè)元素的 value 值。
.offsetParent()ootNodeRE = /^(?:body|html)$/i offsetParent: function() { return this.map(function() { var parent = this.offsetParent || document.body while (parent && !rootNodeRE.test(parent.nodeName) && $(parent).css("position") == "static") parent = parent.offsetParent return parent }) }
查找最近的祖先定位元素,即最近的屬性 position 被設(shè)置為 relative 、absolute 和 fixed 的祖先元素。
var parent = this.offsetParent || document.body
獲取元素的 offsetParent 屬性,如果不存在,則默認(rèn)賦值為 body 元素。
parent && !rootNodeRE.test(parent.nodeName) && $(parent).css("position") == "static"
判斷父級(jí)定位元素是否存在,并且不為根元素(即 body 元素或 html 元素),并且為相對(duì)定位元素,才進(jìn)入循環(huán),循環(huán)內(nèi)是獲取下一個(gè) offsetParent 元素。
這個(gè)應(yīng)該做瀏覽器兼容的吧,因?yàn)?offsetParent 本來(lái)返回的就是最近的定位元素。
.offset()offset: function(coordinates) { if (coordinates) return this.each(function(index) { var $this = $(this), coords = funcArg(this, coordinates, index, $this.offset()), parentOffset = $this.offsetParent().offset(), props = { top: coords.top - parentOffset.top, left: coords.left - parentOffset.left } if ($this.css("position") == "static") props["position"] = "relative" $this.css(props) }) if (!this.length) return null if (document.documentElement !== this[0] && !$.contains(document.documentElement, this[0])) return { top: 0, left: 0 } var obj = this[0].getBoundingClientRect() return { left: obj.left + window.pageXOffset, top: obj.top + window.pageYOffset, width: Math.round(obj.width), height: Math.round(obj.height) } },
獲取或設(shè)置元素相對(duì) document 的偏移量。
先來(lái)看獲取值:
if (!this.length) return null if (document.documentElement !== this[0] && !$.contains(document.documentElement, this[0])) return { top: 0, left: 0 } var obj = this[0].getBoundingClientRect() return { left: obj.left + window.pageXOffset, top: obj.top + window.pageYOffset, width: Math.round(obj.width), height: Math.round(obj.height) }
如果集合不存在,則返回 null
if (document.documentElement !== this[0] && !$.contains(document.documentElement, this[0])) return { top: 0, left: 0 }
如果集合中第一個(gè)元素不為 html 元素對(duì)象(document.documentElement !== this[0]) ,并且不為 html 元素的子元素,則返回 { top: 0, left: 0 }
接下來(lái),調(diào)用 getBoundingClientRect ,獲取元素的 width 和 height 值,以及相對(duì)視窗左上角的 left 和 top 值。具體參見(jiàn)文檔: Element.getBoundingClientRect()
因?yàn)?getBoundingClientRect 獲取到的位置是相對(duì)視窗的,因此需要將視窗外偏移量加上,即加上 window.pageXOffset 或 window.pageYOffset 。
再來(lái)看設(shè)置值:
if (coordinates) return this.each(function(index) { var $this = $(this), coords = funcArg(this, coordinates, index, $this.offset()), parentOffset = $this.offsetParent().offset(), props = { top: coords.top - parentOffset.top, left: coords.left - parentOffset.left } if ($this.css("position") == "static") props["position"] = "relative" $this.css(props) })
前面幾行都是固有的模式,不再展開(kāi),看看這段:
parentOffset = $this.offsetParent().offset()
獲取最近定位元素的 offset 值,這個(gè)值有什么用呢?
props = { top: coords.top - parentOffset.top, left: coords.left - parentOffset.left } if ($this.css("position") == "static") props["position"] = "relative" $this.css(props)
我們可以看到,設(shè)置偏移的時(shí)候,其實(shí)是設(shè)置元素的 left 和 top 值。如果父級(jí)元素有定位元素,那這個(gè) left 和 top 值是相對(duì)于第一個(gè)父級(jí)定位元素的。
因此需要將傳入的 coords.top 和 coords.left 對(duì)應(yīng)減掉第一個(gè)父級(jí)定位元素的 offset 的 top 和 left 值。
如果當(dāng)前元素的 position 值為 static ,則將值設(shè)置為 relative ,相對(duì)自身偏移計(jì)算出來(lái)相差的 left 和 top 值。
.position()position: function() { if (!this.length) return var elem = this[0], offsetParent = this.offsetParent(), offset = this.offset(), parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset() offset.top -= parseFloat($(elem).css("margin-top")) || 0 offset.left -= parseFloat($(elem).css("margin-left")) || 0 parentOffset.top += parseFloat($(offsetParent[0]).css("border-top-width")) || 0 parentOffset.left += parseFloat($(offsetParent[0]).css("border-left-width")) || 0 return { top: offset.top - parentOffset.top, left: offset.left - parentOffset.left } },
返回相對(duì)父元素的偏移量。
offsetParent = this.offsetParent(), offset = this.offset(), parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset()
分別獲取到第一個(gè)定位父元素 offsetParent 及相對(duì)文檔偏移量 parentOffset ,和自身的相對(duì)文檔偏移量 offset 。在獲取每一個(gè)定位父元素偏移量時(shí),先判斷父元素是否為根元素,如果是,則 left 和 top 都返回 0。
offset.top -= parseFloat($(elem).css("margin-top")) || 0 offset.left -= parseFloat($(elem).css("margin-left")) || 0
兩個(gè)元素之間的距離應(yīng)該不包含元素的外邊距,因此將外邊距減去。
parentOffset.top += parseFloat($(offsetParent[0]).css("border-top-width")) || 0 parentOffset.left += parseFloat($(offsetParent[0]).css("border-left-width")) || 0
因?yàn)?position 返回的是距離第一個(gè)定位元素的 context box 的距離,因此父元素的 offset 的 left 和 top 值需要將 border 值加上(offset 算是的外邊距距離文檔的距離)。
return { top: offset.top - parentOffset.top, left: offset.left - parentOffset.left }
最后,將他們距離文檔的偏移量相減就得到兩者間的偏移量了。
.scrollTop()scrollTop: function(value) { if (!this.length) return var hasScrollTop = "scrollTop" in this[0] if (value === undefined) return hasScrollTop ? this[0].scrollTop : this[0].pageYOffset return this.each(hasScrollTop ? function() { this.scrollTop = value } : function() { this.scrollTo(this.scrollX, value) }) },
獲取或設(shè)置元素在縱軸上的滾動(dòng)距離。
先看獲取值:
var hasScrollTop = "scrollTop" in this[0] if (value === undefined) return hasScrollTop ? this[0].scrollTop : this[0].pageYOffset
如果存在 scrollTop 屬性,則直接用 scrollTop 獲取屬性,否則用 pageYOffset 獲取元素Y軸在屏幕外的距離,也即滾動(dòng)高度了。
return this.each(hasScrollTop ? function() { this.scrollTop = value } : function() { this.scrollTo(this.scrollX, value) })
知道了獲取值后,設(shè)置值也簡(jiǎn)單了,如果有 scrollTop 屬性,則直接設(shè)置這個(gè)屬性的值,否則調(diào)用 scrollTo 方法,用 scrollX 獲取到 x 軸的滾動(dòng)距離,將 y 軸滾動(dòng)到指定的距離 value。
.scrollLeft()scrollLeft: function(value) { if (!this.length) return var hasScrollLeft = "scrollLeft" in this[0] if (value === undefined) return hasScrollLeft ? this[0].scrollLeft : this[0].pageXOffset return this.each(hasScrollLeft ? function() { this.scrollLeft = value } : function() { this.scrollTo(value, this.scrollY) }) },
scrollLeft 原理同 scrollTop ,不再展開(kāi)敘述。
width/height 方法生成器["width", "height"].forEach(function(dimension) { var dimensionProperty = dimension.replace(/./, function(m) { return m[0].toUpperCase() }) $.fn[dimension] = function(value) { var offset, el = this[0] if (value === undefined) return isWindow(el) ? el["inner" + dimensionProperty] : isDocument(el) ? el.documentElement["scroll" + dimensionProperty] : (offset = this.offset()) && offset[dimension] else return this.each(function(idx) { el = $(this) el.css(dimension, funcArg(this, value, idx, el[dimension]())) }) } })
這個(gè)函數(shù)用來(lái)生成 width 和 height 方法。
var dimensionProperty = dimension.replace(/./, function(m) { return m[0].toUpperCase() })
這段將 width 和 height 的首字母變成大寫,即 Width 和 Height 的形式。
width 和 height 同樣有獲取值和設(shè)置值的功能,先來(lái)看獲取值的實(shí)現(xiàn)。
isWindow(el) ? el["inner" + dimensionProperty] : isDocument(el) ? el.documentElement["scroll" + dimensionProperty] : (offset = this.offset()) && offset[dimension]
如果第一個(gè)元素為 window 對(duì)象,則用 innerWidth 或 innerHeight 獲取值。window 關(guān)于寬高的屬性有 innerWidth 、 innerHeight 和 outerWidth 、outerHeight ,inner 相關(guān)的屬性是獲取瀏覽器視窗的寬度或者高度,而 outer 相關(guān)的屬性獲取是的整個(gè)瀏覽器的寬度或高度,包含標(biāo)簽欄,地址欄等。
如果是 document 對(duì)象,則用 el.documentElement.scrollWidth 或 el.documentElement.scrollHeight 來(lái)獲取值。document.documentElement 對(duì)象上有 scrollWidth/scrollHeight 、 offsetWidth/offsetHeight 和 clientWidth/clientHeight 等寬高相關(guān)的屬性,三者有什么區(qū)別呢,可以看看這篇文章:《web前端學(xué)習(xí)筆記---scrollWidth,clientWidth,offsetWidth的區(qū)別》
對(duì)于普通元素,獲取值就簡(jiǎn)單了,調(diào)用的是上面說(shuō)到過(guò)的 offset 方法,就能取到對(duì)應(yīng)的 width 和 height 的值了。
this.each(function(idx) { el = $(this) el.css(dimension, funcArg(this, value, idx, el[dimension]())) })
設(shè)置值就相對(duì)簡(jiǎn)單了,調(diào)用的是 css 方法,直接設(shè)置對(duì)應(yīng)的屬性就可以了。關(guān)于 css 方法的實(shí)現(xiàn),可以看看上篇:《讀Zepto源碼之樣式操作》
系列文章讀Zepto源碼之代碼結(jié)構(gòu)
讀 Zepto 源碼之內(nèi)部方法
讀Zepto源碼之工具函數(shù)
讀Zepto源碼之神奇的$
讀Zepto源碼之集合操作
讀Zepto源碼之集合元素查找
讀Zepto源碼之操作DOM
讀Zepto源碼之樣式操作
參考MDN:Node.textContent
data-*
Element.getBoundingClientRect()
window
web前端學(xué)習(xí)筆記---scrollWidth,clientWidth,offsetWidth的區(qū)別
?
License最后,所有文章都會(huì)同步發(fā)送到微信公眾號(hào)上,歡迎關(guān)注,歡迎提意見(jiàn):
作者:對(duì)角另一面
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/83653.html
摘要:的模塊用來(lái)獲取節(jié)點(diǎn)中的屬性的數(shù)據(jù),和儲(chǔ)存跟相關(guān)的數(shù)據(jù)。獲取節(jié)點(diǎn)指定的緩存值。如果存在,則刪除指定的數(shù)據(jù),否則將緩存的數(shù)據(jù)全部刪除。為所有下級(jí)節(jié)點(diǎn),如果為方法,則節(jié)點(diǎn)自身也是要被移除的,所以需要將自身也加入到節(jié)點(diǎn)中。 Zepto 的 Data 模塊用來(lái)獲取 DOM 節(jié)點(diǎn)中的 data-* 屬性的數(shù)據(jù),和儲(chǔ)存跟 DOM 相關(guān)的數(shù)據(jù)。 讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡...
摘要:所以模塊依賴于模塊,在引入前必須引入模塊。原有的方法分析見(jiàn)讀源碼之樣式操作方法首先調(diào)用原有的方法,將元素顯示出來(lái),這是實(shí)現(xiàn)動(dòng)畫(huà)的基本條件。如果沒(méi)有傳遞,或者為值,則表示不需要?jiǎng)赢?huà),調(diào)用原有的方法即可。 fx 模塊提供了 animate 動(dòng)畫(huà)方法,fx_methods 利用 animate 方法,提供一些常用的動(dòng)畫(huà)方法。所以 fx_methods 模塊依賴于 fx 模塊,在引入 fx_m...
摘要:讀源碼系列文章已經(jīng)放到了上,歡迎源碼版本本文閱讀的源碼為改寫原有的方法模塊改寫了以上這些方法,這些方法在調(diào)用的時(shí)候,會(huì)為返回的結(jié)果添加的屬性,用來(lái)保存原來(lái)的集合。方法的分析可以看讀源碼之模塊。 Stack 模塊為 Zepto 添加了 addSelf 和 end 方法。 讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡迎star: reading-zepto 源碼版本 本文閱讀的...
摘要:模塊處理的是表單提交。表單提交包含兩部分,一部分是格式化表單數(shù)據(jù),另一部分是觸發(fā)事件,提交表單。最終返回的結(jié)果是一個(gè)數(shù)組,每個(gè)數(shù)組項(xiàng)為包含和屬性的對(duì)象。否則手動(dòng)綁定事件,如果沒(méi)有阻止瀏覽器的默認(rèn)事件,則在第一個(gè)表單上觸發(fā),提交表單。 Form 模塊處理的是表單提交。表單提交包含兩部分,一部分是格式化表單數(shù)據(jù),另一部分是觸發(fā) submit 事件,提交表單。 讀 Zepto 源碼系列文章已...
摘要:模塊基于上的事件的封裝,利用屬性,封裝出系列事件。這個(gè)判斷需要引入設(shè)備偵測(cè)模塊。然后是監(jiān)測(cè)事件,根據(jù)這三個(gè)事件,可以組合出和事件。其中變量對(duì)象和模塊中的對(duì)象的作用差不多,可以先看看讀源碼之模塊對(duì)模塊的分析。 Gesture 模塊基于 IOS 上的 Gesture 事件的封裝,利用 scale 屬性,封裝出 pinch 系列事件。 讀 Zepto 源碼系列文章已經(jīng)放到了github上,歡...
摘要:模塊是為解決移動(dòng)版加載圖片過(guò)大過(guò)多時(shí)崩潰的問(wèn)題。因?yàn)闆](méi)有處理過(guò)這樣的場(chǎng)景,所以這部分的代碼解釋不會(huì)太多,為了說(shuō)明這個(gè)問(wèn)題,我翻譯了這篇文章作為附文怎樣處理移動(dòng)端對(duì)圖片資源的限制,更詳細(xì)地解釋了這個(gè)模塊的應(yīng)用場(chǎng)景。 assets 模塊是為解決 Safari 移動(dòng)版加載圖片過(guò)大過(guò)多時(shí)崩潰的問(wèn)題。因?yàn)闆](méi)有處理過(guò)這樣的場(chǎng)景,所以這部分的代碼解釋不會(huì)太多,為了說(shuō)明這個(gè)問(wèn)題,我翻譯了《How to...
閱讀 3437·2021-10-11 11:06
閱讀 2212·2019-08-29 11:10
閱讀 1969·2019-08-26 18:18
閱讀 3280·2019-08-26 13:34
閱讀 1589·2019-08-23 16:45
閱讀 1064·2019-08-23 16:29
閱讀 2829·2019-08-23 13:11
閱讀 3264·2019-08-23 12:58