$.each:css
/** * 以集合每個元素做爲上下文,來執行回調函數 * @param elements * @param callback * @returns {*} */ $.each = function(elements, callback){ var i, key if (likeArray(elements)) { //數組、僞數組 for (i = 0; i < elements.length; i++) if (callback.call(elements[i], i, elements[i]) === false) return elements } else { for (key in elements) //對象 if (callback.call(elements[key], key, elements[key]) === false) return elements } return elements }
這裏的elements能夠是數組或者對象,若是是對象,則會將其原型裏面的屬性也遍歷出來,最後返回elments自己,若是回調函數返回了false,則終止循環html
remove:node
/** * 刪除元素集 * 原理 parentNode.removeChild * @returns {*} */ remove: function(){ //遍歷到其父元素 removeChild return this.each(function(){ if (this.parentNode != null) this.parentNode.removeChild(this) }) },
這裏的重點是parentNode.removeChild(this); 若是是沒有父節點的這裏不會執行。正則表達式
is:數組
//返回集合中的第1條記錄是否與selector匹配 is: function(selector){ return this.length > 0 && zepto.matches(this[0], selector) }
例如$("#id").is(".hasClass"); 實際就是調用matches進行匹配緩存
not:
app
//排除集合裏知足條件的記錄,接收參數爲:css選擇器,function, dom ,nodeList not: function(selector){ var nodes=[] //當selector爲函數時,safari下的typeof nodeList也是function,因此這裏須要再加一個判斷selector.call !== undefined if (isFunction(selector) && selector.call !== undefined) this.each(function(idx){ //注意這裏收集的是selector.call(this,idx)返回結果爲false的時候記錄 if (!selector.call(this,idx)) nodes.push(this) }) else { //當selector爲字符串的時候,對集合進行篩選,也就是篩選出集合中知足selector的記錄 var excludes = typeof selector == 'string' ? this.filter(selector) : //當selector爲nodeList時執行slice.call(selector),注意這裏的isFunction(selector.item)是爲了排除selector爲數組的狀況 //當selector爲css選擇器,執行$(selector) (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector); this.forEach(function(el){ //篩選出不在excludes集合裏的記錄,達到排除的目的 if (excludes.indexOf(el) < 0) nodes.push(el) }) } return $(nodes)//因爲上面獲得的結果是數組,這裏須要轉成zepto對象,以便繼承其它方法,實現鏈寫 },
這裏首先判斷selector是否爲函數,若是是,則遍歷執行函數,若是返回false,則push到數組中dom
若是css選擇字符串則調用this.filter(seelctor),這裏有個小技巧使得not和filter相互調用wordpress
若是是數組或對象,則直接返回$(他本身)函數
最後遍歷this,只要不是在excludes裏面的都是知足條件的
has:
/* 接收node和string做爲參數,給當前集合篩選出包含selector的集合 isObject(selector)是判斷參數是不是node,由於typeof node == 'object' 當參數爲node時,只須要判讀當前記當裏是否包含node節點便可 當參數爲string時,則在當前記錄裏查詢selector,若是長度爲0,則爲false,filter函數就會過濾掉這條記錄,不然保存該記錄 */ has: function(selector){ return this.filter(function(){ return isObject(selector) ? $.contains(this, selector) : $(this).find(selector).size() }) },
重點提示下:這裏的this若是也知足selector,則最後返回的結果集裏也會有this
show:
/**
* 獲取元素的默認display屬性
* 是爲了兼容什麼?
* @param nodeName
* @returns {*}
*/
function defaultDisplay(nodeName) {
var element, display
if (!elementDisplay[nodeName]) { //緩存裏沒有
element = document.createElement(nodeName)
document.body.appendChild(element)
display = getComputedStyle(element, '').getPropertyValue("display")
element.parentNode.removeChild(element)
// display == "none",設置成blaock,即隱藏-顯示
display == "none" && (display = "block")
elementDisplay[nodeName] = display //TODO:緩存元素的默認display屬性,緩存幹嗎?
}
return elementDisplay[nodeName]
}
/** * 展現 * @returns {*} */ show: function(){ return this.each(function(){ //清除內聯樣式display="none" this.style.display == "none" && (this.style.display = '') //計算樣式display爲none時,重賦顯示值 if (getComputedStyle(this, '').getPropertyValue("display") == "none") this.style.display = defaultDisplay(this.nodeName) //defaultDisplay是獲取元素默認display的方法 }) },
this.style.display = ' '是清除元素的style裏面的display樣式,恢復元素的默認樣式。
getComputedStyle(dom)能獲取dom的全部css樣式,第二個參數能夠不傳
getComputedStyle(dom,":after")能獲取dom的:after僞類的全部css樣式(這裏只談移動端)
詳情請看:http://www.zhangxinxu.com/wordpress/2012/05/getcomputedstyle-js-getpropertyvalue-currentstyle/
若是清除了style裏面的display屬性仍是無效的話,直接顯式的給display賦默認值,defaultDisplay的內部實際是在document裏面新添加一個元素,來獲取默認值的。
css:
/** * 讀寫樣式 寫:內聯樣式 讀:計算樣式 * 原理 讀:elment[style]/getComputedStyle, 寫 this.style.cssText 行內樣式設值 * @param property String/Array/Fun * @param value * @returns {*} */ css: function(property, value){ //只有一個傳參,讀 if (arguments.length < 2) { var computedStyle, element = this[0] if(!element) return //getComputedStyle是一個能夠獲取當前元素全部最終使用的CSS屬性值。返回的是一個CSS樣式聲明對象([object CSSStyleDeclaration]),只讀 //讀到計算樣式 computedStyle = getComputedStyle(element, '') //設置樣式 if (typeof property == 'string')// 字符串 //優先讀行內樣式,再讀計算樣式,行內樣式級別最高? TODO:彷佛有bug,若是設置了!important 呢 return element.style[camelize(property)] || computedStyle.getPropertyValue(property) else if (isArray(property)) { //數組 var props = {} $.each(property, function(_, prop){ //遍歷讀取每一條樣式,存入JSON,返回 props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop)) }) return props } } //若是是寫 var css = '' if (type(property) == 'string') { if (!value && value !== 0) //null,undefined時,刪掉樣式 this.each(function(){ //刪除 dasherize是將字符串轉換成css屬性(background-color格式) this.style.removeProperty(dasherize(property)) }) else //‘-’格式值 + px單位 css = dasherize(property) + ":" + maybeAddPx(property, value) } else { for (key in property) //是對象時 if (!property[key] && property[key] !== 0) //當property[key]的值爲null/undefined,刪除屬性 this.each(function(){ this.style.removeProperty(dasherize(key)) }) else //‘-’格式值 + px單位 css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';' } //設值 //TODO: this.style.cssText += 未考慮去重了 return this.each(function(){ this.style.cssText += ';' + css }) },
判斷只傳了一個參數:arguments.length < 2 或者 1 in arguments,
流程大體以下:
1:判斷參數,若是是一個參數則爲只讀模式
1.2:若是property爲字符串,則 直接獲取元素的css屬性值
1.3:若是property爲數組,則this.each遍歷數組,獲取每一個屬性的value值並造成props對象返回
2:如有2個參數,爲寫模式
2.1:若是property爲字符串,則style.cssText+= property:value(這裏的處理沒有去重,但本人測了一下,這並不影響頁面的渲染)
2.2:若是property爲對象,則循環遍歷property
這裏有幾個函數要提一下:
camelize() 將帶「—」的轉爲駝峯命名例如「background-color」轉爲「backgroundColor」,對象屬性是必須駝峯命名的。
dasherize() 將「backgroundColor」轉爲「background-color」,內部實現是用正則表達式匹配
style.removeProperty 刪除style中的某個屬性
style.setProperty(property,value,priority) 設置style中的某個屬性,priority可取「important」 ,(不太明白爲何zepto不用這個方法,望高人指教)
maybeAddPx (property,value):根據property類型給value加上「px」後綴
html:
/**
* 處理 arg爲函數/值
* 爲函數,返回函數返回值
* 爲值,返回值
* @param context
* @param arg
* @param idx
* @param payload
* @returns {*}
*/
function funcArg(context, arg, idx, payload) {
return isFunction(arg) ? arg.call(context, idx, payload) : arg
}
/** * 讀寫元素HTML內容 * 原理 經過innerHTML讀內容,append()寫內容 * @param html * @returns {*|string|string|string|string|string} */ html: function(html){ return 0 in arguments ? this.each(function(idx){ var originHtml = this.innerHTML //記錄原始的innerHTMl //若是參數html是字符串直接插入到記錄中, //若是是函數,則將當前記錄做爲上下文,調用該函數,且傳入該記錄的索引和原始innerHTML做爲參數 $(this).empty().append( funcArg(this, html, idx, originHtml) ) }) : (0 in this ? this[0].innerHTML : null) },
html():不傳參數則獲取元素的innerHTML,
html("<div></div>"):設置元素的innerHTML
html(function(){....}):可傳入方法,返回值設置爲元素的innerHTML
這裏的funcArg的功能是判斷html爲函數則以this爲上下文,以idx,originHtml爲參數執行函數
text:
/** * 讀寫元素文本內容 * 原理: 經過 textContent 讀寫文本 * @param text * @returns {*} */ 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[0].textContent : null) //未傳參讀 },