width height 模板方法 讀寫width/heightjavascript
['width', 'height'].forEach(function(dimension){ //將width,hegiht轉成Width,Height,用於document獲取 var dimensionProperty = dimension.replace(/./, function(m){ return m[0].toUpperCase() }) $.fn[dimension] = function(value){ var offset, el = this[0] //讀時,是window 用innerWidth,innerHeight獲取 if (value === undefined) return isWindow(el) ? el['inner' + dimensionProperty] : //是document,用scrollWidth,scrollHeight獲取 isDocument(el) ? el.documentElement['scroll' + dimensionProperty] : (offset = this.offset()) && offset[dimension] //TODO:不然用 offsetWidth offsetHeight //寫 else return this.each(function(idx){ el = $(this) //設值,支持value爲函數 el.css(dimension, funcArg(this, value, idx, el[dimension]())) }) } })
/./ 是匹配除換行(\n)之外全部的字符,不加/g,只會匹配一個字符,這裏匹配的是h或wcss
var name = "height".replace(/./,function(m){ console.log(m); return m[0].toUpperCase()});
console.log(name);
h
Heighthtml
<div id="high" style="width: 150px;height: 41px;float: left;border: 2px solid red;margin: 10px;padding: 10px;background-color: blue;" id="test"> <div style="height:100%;"></div> </div> $("#high").height() 65 $("#high")[0].offsetHeight 65
$("#high").height()即offsetHeight包含content,padding,border在內,style=「height:41px」 指的是content爲41px;由於默認樣式爲:box-sizing:content-box,若是指定box-sizing:border-box;則sthle=「height:41px",指的是offsetHeight爲41px;java
offsetHeight:指的是元素視口高度。node
scrollHeight:指的是元素內部的實際高度,所以document求高度要用到它。數組
innerHeight: 只讀屬性,聲明瞭窗口的文檔顯示區的高度和寬度,以像素計。這裏的寬度和高度不包括菜單欄、工具欄以及滾動條等的高度。閉包
document.documentElement.clientHeight:與window.innerHeight的效果同樣app
outerHeight: 只讀屬性,聲明瞭窗口的高度,包含工具欄。ide
詳細信息請點擊:http://www.cnblogs.com/yuteng/articles/1894578.html函數
注意: 這裏的height()能夠接受函數做爲參數
Generate the "after","prepend","before","append","insertAfter","insertBefore","appendTo", and "prependTo" methods adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ],
adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ],
adjacencyOperators.forEach(function(operator, operatorIndex) { var inside = operatorIndex % 2 //=> prepend, append 有餘數 注意forEach遍歷出的索引從0開始 $.fn[operator] = function(){ // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings //nodes HTML字符串生成的DOM集 var argType, nodes = $.map(arguments, function(arg) { argType = type(arg) //傳參非 object、array、null,就直接調用zepto.fragment生成DOM return argType == "object" || argType == "array" || arg == null ? arg : zepto.fragment(arg) }), //若是$長度>1,須要克隆裏面的元素 parent, copyByClone = this.length > 1 if (nodes.length < 1) return this //爲0,不須要操做,直接返回 //遍歷源$,執行插入 _指代此參數無效或不用 return this.each(function(_, target){ parent = inside ? target : target.parentNode //prepend, append取父元素 // convert all methods to a "before" operation //用insertBefore模擬實現 target = operatorIndex == 0 ? target.nextSibling : //after,target等於下一個兄弟元素,而後將DOM經過insertBefore插入到target前 operatorIndex == 1 ? target.firstChild : //prepend target爲parent的第一個元素,而後將DOM經過insertBefore插入到target前 operatorIndex == 2 ? target : // before 直接將將DOM經過insertBefore插入到target前 null // append 直接調用$(target).append //父元素是否在document中 var parentInDocument = $.contains(document.documentElement, parent) //遍歷待插入的元素 nodes.forEach(function(node){ //克隆 if (copyByClone) node = node.cloneNode(true) //定位元素不存在,,無法執行插入操做,直接刪除,返回 else if (!parent) return $(node).remove() //插入節點後,若是被插入的節點是SCRIPT,則執行裏面的內容並將window設爲上下文 //插入元素 parent.insertBefore(node, target) //若是父元素在document裏,修正script標籤。緣由是script標籤經過innerHTML加入DOM不執行。須要在全局環境下執行它 if (parentInDocument) traverseNode(node, function(el){ if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' && (!el.type || el.type === 'text/javascript') && !el.src) window['eval'].call(window, el.innerHTML) }) }) }) } // after => insertAfter // prepend => prependTo // before => insertBefore // append => appendTo /** * 插入方法轉換 * @param html * @returns {*} */ $.fn[inside ? operator+'To' : 'insert'+(operatorIndex ? 'Before' : 'After')] = function(html){ $(html)[operator](this) return
this } })
由於 ’after‘,’prepend‘,’before‘,’append‘ 均可用insertBefore來實現,因此這四個函數的內容格式是同樣的,這裏就能夠用工廠模式來循環生產這四個函數。
這裏大體流程以下:
// 可傳遞多個參數包括字符串和對象
$.fn[operator] = function () {
// arguments.map 針對arguments裏面的數組進行處理,將裏面的字符串項轉化爲對象
// this.forEach 循環對每個調用者target作對應操做
// 因最後要作parent.insertBefore操做,因此這裏要根據operator 確認與target有關的parent
// 因用insertBefore來模擬實現,這裏要選擇對應的參照節點並統一賦值給target
// 執行 parent.insertBefore(node, target);
// 若是node爲script,則還必須將裏面的腳本內容用window.eval()來執行
}
這裏有幾個小技巧說一下:
1:inside = operatorIndex % 2 ,parent = inside?target:target.parentNode若是對一個數組中的特定項進行不一樣的操做,能夠對索引取餘數,由於在js裏面0表明false,正數表明true
2:target.nextSibling 表示取節點的下一個兄弟節點,這裏通過測試,若是target在頁面上爲最後一個節點,則target.nextSibling 依然會返回一個虛擬節點,以下例子
$("#high")[0].nextSibling
結果: #text baseURI: "file:///home/zhutao/Documents/lib/zepto/test/defer.html" childNodes: NodeList[0] data: "↵" firstChild: null lastChild: null length: 1 nextElementSibling: null nextSibling: null nodeName: "#text" nodeType: 3 nodeValue: "↵" ownerDocument: document parentElement: div#first.test parentNode: div#first.test previousElementSibling: div#high previousSibling: div#high textContent: "↵" wholeText: "↵" __proto__: CharacterData
3:node.cloneNode(deep),deep爲true,則將子節點也clone進去,不然不會clone子節點,這跟clone對象是一個道理,例子以下:
$("#clone")[0].cloneNode(true); <div id="clone" data-test="測試" style="height:50px;width: 50px;border:1px solid red;overflow: hidden"> <div data-index="1111">clone測試</div> </div> $("#clone")[0].cloneNode(); <div id="clone" data-test="測試" style="height:50px;width: 50px;border:1px solid red;overflow: hidden"></div>
4:window.eval() 與 eval()的區別:window.eval() = window.eval.call(window,script); eval() = window.eval.call(this,script); ,eval()常在閉包函數使用 這裏的this指的是閉包的環境變量。以下例子 :
var x = 5; function fn(){ var x = 'jack'; window.eval('x=10;'); } fn(); console.log(x); // -->5 10 undefined var x = 5; function fn(){ var x = 'jack'; eval('x=10;'); } fn(); console.log(x); // -->5 5 undefined
(例子來自:http://www.cnblogs.com/snandy/archive/2011/03/16/1986055.html)