摘要:注意可能因為元素換行的原因返回的是節(jié)點。該規(guī)范對于使用和接口的對象都增了兩種新方法返回節(jié)點子樹內與之相匹配的第一個節(jié)點。指定的元素的子樹會被搜索,包括元素自己。第一個參數是事件名,第二個是回調函數,第三個參數為表示捕獲,表示冒泡。
打個招聘廣告: 杭州 阿里巴巴B2B 招前端(想去西溪的也可幫推薦),比較缺人,機會多多!廣告位長期有效,有興趣簡歷我郵箱:854936875@qq.com
看圖識文(取自 寒冬winter 的微博)。
文章里引用了MDN和《javascript高級程序設計3》里的知識。
如有不對的地方,敬請指出。
創(chuàng)建元素:document.createElement()
使用document.createElement()可以創(chuàng)建新元素。這個方法只接受一個參數,即要創(chuàng)建元素的標簽名。這個標簽名在HTML文檔中不區(qū)分大小寫,在XHTML中區(qū)分大小寫。
var div = document.createElement("div");
使用createElement()方法創(chuàng)建新元素的同時,也為新元素設置了ownerDocument屬性,可以操作元素的特性。
div.id = "myDiv"; div.className = "div1";
此時,新元素尚未被添加到文檔樹中,因此設置各種特性均不會影響瀏覽器的顯示。要添加到文檔樹,可用appendChild()、insertBefore()、replaceChild()。(稍后講到)
document.body.appendChild(div);
當把元素添加到文檔樹中后,伺候鬼這個元素做的任何修改都會實時地反應到瀏覽器中。
在IE中可以為createElement()方法傳入完整的元素標簽和屬性。(只在IE中兼容)
var div = document.createElement(""); 不能再標簽里加其他元素節(jié)點或者文本節(jié)點,如下的方式和上面的得出的節(jié)點一樣 var div = document.createElement("12212");
創(chuàng)建文本節(jié)點 :document.createTextNode
使用document.createTextNode()來創(chuàng)建文本節(jié)點,這個方法接受一個參數:要插入節(jié)點的文本。與設置已有文本節(jié)點的值一樣,作為參數的文本將按照HTML或XML的格式進行編碼。
document.createTextNode("121212");
可以添加多個文本節(jié)點。假如兩個文本節(jié)點時相鄰的同胞節(jié)點,那么兩個文本節(jié)點會連起來,中間不會有空格。
2.節(jié)點關系(IE9以前不將換行和空格看做文本節(jié)點,其他瀏覽器會)
文本關系如下:
234
父節(jié)點:parentNode
parentNode是指定節(jié)點的父節(jié)點.一個元素節(jié)點的父節(jié)點可能是一個元素(Element )節(jié)點,也可能是一個文檔(Document )節(jié)點,或者是個文檔碎片(DocumentFragment)節(jié)點.
每一個節(jié)點都有一個parentNode屬性。
對于下面的節(jié)點類型: Attr, Document, DocumentFragment, Entity, Notation,其parentNode屬性返回null。如果當前節(jié)點剛剛被建立,還沒有被插入到DOM樹中,則該節(jié)點的parentNode屬性也返回null。
子節(jié)點:childNodes
childNodes 返回包含指定節(jié)點的子節(jié)點的集合,該集合為即時更新的集合(live collection)。
即時更新就是對節(jié)點元素的任意修改都會立即反映到結果里。
兄弟節(jié)點:nextSibling,previousSibling
nextSibling返回某節(jié)點的下一個兄弟節(jié)點,previousSibling返回某節(jié)點的上一個兄弟節(jié)點,沒有的話返回null。
注意:可能因為元素換行的原因返回的是text節(jié)點。
第一個或最后一個子節(jié)點:firstChild、lastChild
firstChild返回node的子節(jié)點中的第一個節(jié)點的引用,沒有返回null
lastChild返回node的子節(jié)點中的最后一個節(jié)點的引用,沒有返回null
只算元素,不算文本節(jié)點。
以下三個方法用法和節(jié)點關系完全一樣,只是這三個方法只看元素節(jié)點,不管因為空格、換行造成的文本節(jié)點或者手動加上去的文本節(jié)點。
children: 返回所有元素子節(jié)點(IE5+、ff3.5、opera3、chrome,但在IE8及以下會將注釋節(jié)點看成一個元素節(jié)點)
以下兩個IE9+才支持
nextElementSibling:返回元素的下一個兄弟元素節(jié)點
previousElementSibling: 返回元素的上一個兄弟元素節(jié)點
appendChild()
appendChild()用于向childNodes列表的末尾添加一個節(jié)點,并且返回這個新增的節(jié)點。
如果傳入到appendChild()里的節(jié)點已經是文檔的一部分了,那結果就是將節(jié)點從原來的位置轉移到新位置,任何一個節(jié)點不能同時出現(xiàn)在文檔中的多個位置。
var returnNode = someNode.appendChild(someNode.firstChild); // 返回第一個節(jié)點 console.log(returnNode === someNode.firstChild); // false console.log(returnNode === someNode.lastChild); // true
insetBefore()
insetBefore()可以將節(jié)點插入到某個特定的位置。這個方法接受兩個參數:要插入的節(jié)點和作為參照的節(jié)點。
插入節(jié)點后,被插入的節(jié)點變成參照節(jié)點的前一個同胞節(jié)點,同時被方法返回。 如果參照節(jié)點是null,則與appendChild()執(zhí)行相同的操作。
// 插入后成為最后一個子節(jié)點 var returnNode = someNode.insetBefore(newNode, null); console.log(returnNode === someNode.lastChild); // true // 插入后成為第一個子節(jié)點 var returnNode = someNode.insetBefore(newNode, someNode.firstChild); console.log(returnNode === newNode); // true console.log(returnNode === someNode.firstChild); // true // 插入到最后一個子節(jié)點的前面 var returnNode = someNode.insetBefore(newNode, someNode.lastChild); console.log(returnNode === someNode.childNodes[someNode.childnodes.length - 2]) // true
替換節(jié)點: replaceChild()
replaceChild()接受兩個參數:要插入的節(jié)點和要被替換的節(jié)點。被替換的節(jié)點將由這個方法返回并從文檔中被移除,同時由要插入的節(jié)點占據其位置。
// 替換第一個子節(jié)點 var returnNode = someNode.replaceChild(newNode, someNode.firstChild);
使用replaceChild()后,被替換的節(jié)點的所有關系指針都會被復制到插入的節(jié)點上面。
刪除節(jié)點:removeChild()
該方法移除節(jié)點,接受一個參數,即要移除的節(jié)點,同時該方法返回被移除的節(jié)點。只能是一個節(jié)點,不能是一組節(jié)點。
// 移除第一個子節(jié)點 var returnNode = someNode.removeChild(newNode, someNode.firstChild);
克隆節(jié)點:cloneNode(true/false)
返回調用該方法的節(jié)點的一個副本。參數表示是否采用深度克隆,如果為true,則該節(jié)點的所有后代節(jié)點也都會被克隆,如果為false,則只克隆該節(jié)點本身,文本或者換行、空格這些不會復制,因為他們都是一個textNode。
注意: 在DOM4規(guī)范中(實現(xiàn)于Gecko 13.0(Firefox 13.0 / Thunderbird 13.0 / SeaMonkey 2.10) , 查看 bug 698391),deep是一個可選參數. 如果省略的話, deep參數的默認值為true,也就是說,深度克隆是默認的.如果想使用淺克隆, 你需要將該參數指定為false。
在舊版本的瀏覽器中, 你始終需要指定deep參數。
克隆一個元素節(jié)點會拷貝它所有的屬性以及屬性值,當然也就包括了屬性上綁定的事件(比如onclick="alert(1)"),但不會拷貝那些使用addEventListener()方法或者node.onclick = fn這種用JavaScript動態(tài)綁定的事件。
注意:為了防止一個文檔中出現(xiàn)兩個ID重復的元素,使用cloneNode()方法克隆的節(jié)點在需要時應該指定另外一個與原ID值不同的ID
var div1 = document.getElementById("div1"); var cloneHtml = div1.cloneNode(true); document.body.appendChild(cloneHtml);5.元素選擇
HTML代碼示例:
2
34
querySelector、querySelectorAll(IE8及以上)
Selectors API通過匹配一組選擇器的方式來為從DOM中檢索Element節(jié)點提供一些簡單快捷的方法,這比過去必須要在javascript代碼中用循環(huán)來查找某個你想要的特定元素更快一些。
該規(guī)范對于使用Document,DocumentFragment和Element接口的對象都增了兩種新方法:
querySelector
返回節(jié)點子樹內與之相匹配的第一個Element節(jié)點。如果沒有匹配的節(jié)點,則返回null。
querySelectorAll
返回一個包含節(jié)點子樹內所有與之相匹配的Element節(jié)點列表,如果沒有相匹配的,則返回一個空節(jié)點列表。
注意:由 querySelector()、querySelectorAll()返回的節(jié)點列表不是動態(tài)實時的(非live Collection)。這和其他DOM查詢方法返回動態(tài)實時節(jié)點列表不一樣。
選擇器方法接受一個或多個用逗號分隔的選擇器來確定需要被返回的元素。例如,要選擇文檔中所有CSS的類(class)是warning或者note的段落(p)元素,可以這樣寫:
var special = document.querySelectorAll( "p.warning, p.note" );
也可以通過ID來查詢,例如:
var el = document.querySelector( "#main, #basic, #exclamation" );
執(zhí)行上面的代碼后,el就包含了文檔中元素的ID是main,basic或exclamation的所有元素中的第一個元素。
querySelector() and querySelectorAll() 里可以使用任何CSS選擇器,他們都不是live Collection:
var notLive = document.querySelectorAll("p"); console.log(notLive); document.getElementById("div1").removeChild(document.getElementById("div2")); console.log(notLive); // 上面兩個輸出都是輸出 `p#div2.one`的引用,沒有因為刪除了`p`標簽而使`notLive`的結果發(fā)生變化。
getElementById()
返回一個匹配特定 ID的元素。id是大小寫敏感的字符串,代表了所要查找的元素的唯一ID,如果沒有則返回null。
如果新建一個元素,還沒有插入到文檔中,則不能通過該方法獲取到。
var notLive = document.getElementById("div2"); console.log(notLive.innerHTML); document.getElementById("div1").removeChild(document.getElementById("div2")); console.log(notLive.innerHTML); // 上面輸出都是2,說明getElementById()也是**非**live collection
getElementsByTagName()
document.getElementsByTagName() 方法返回一個實時的包含具有給出標簽名的元素們的HTMLCollection。指定的元素的子樹會被搜索,包括元素自己。返回的 list 是實時的(live collection),意味著它會隨著DOM樹的變化自動更新。因此,如果對同一個元素,使用相同的參數,是不需要多次調用document.getElementsByTagName() 的。
Element.getElementsByTagName()的搜索被限制為指定元素的后代而不是document
var live = document.getElementsByTagName("p"); console.log(live[0].innerHTML); document.getElementById("div1").removeChild(document.getElementById("div2")); console.log(live[0].innerHTML); // 第一個輸出2,第二個報錯,因為無法引用到p標簽
getElementsByName()
該方法返回一個實時的nodelist collection,包含文檔中所有name屬性匹配的標簽。這是一個**live collection**。
注意:在IE和opera下,如果某個元素1的name和另一個元素2的id重合,且元素2在元素1的前面,則getElementsByName()會取到元素2。
var live = document.getElementsByName("div2"); console.log(live[0].innerHTML); document.getElementById("div1").removeChild(document.getElementById("div2")); console.log(live[0].innerHTML); // chrome下:全部輸出4 // IE下: 第一個輸出2,第二個報錯。
getElementsByClassName()
該方法返回一個即時更新的(live) HTMLCollection,包含了所有擁有指定 class 的子元素。當在 document 對象上調用此方法時,會檢索整個文檔,包括根元素。(IE9以下不支持)
要匹配多個class,則className用空格分開。
getElementsByClassName("class1 class2");
var live = document.getElementsByClassName("one"); console.log(live[0].innerHTML); document.getElementById("div1").removeChild(document.getElementById("div2")); console.log(live[0].innerHTML); // 第一個返回2,第二個報錯6.屬性操作
setAttribute()
添加一個新屬性(attribute)到元素上,或改變元素上已經存在的屬性的值。
當在 HTML 文檔中的 HTML 元素上調用 setAttribute() 方法時,該方法會將其屬性名稱(attribute name)參數小寫化。
如果指定的屬性已經存在,則其值變?yōu)閭鬟f的值。如果不存在,則創(chuàng)建指定的屬性。也可指定為null。如果設置為null,最好使用removeAttribute()。
var div2 = document.getElementById("div2"); div2.setAttribute("class", "new_class"); div2.setAttribute("id", "new_id");
注意:在IE7下,修改了元素的class,如果已有class,則會出現(xiàn)兩個class,通過setAttribute()添加的不生效;如果沒有class,則添加上class,但這個添加上去的class的樣式不會生效。
removeAttribute()
該方法用于移除元素的屬性。
var div2 = document.getElementById("div2"); div2.removeAttribute("class");
注意:IE7下無法移除 class 屬性
getAttribute()
該方法返回元素上指定屬性(attribute)的值。如果指定的屬性不存在,則返回 null 或 "" (空字符串)(IE5+都返回null)。
var div2 = document.getElementById("div2"); var attr = div2.getAttribute("class"); console.log(attr);
注意:IE7下不能正確返回class,返回的是null,其他正常。
hasAttribute()
hasAttribute() 返回一個布爾值,指示該元素是否包含有指定的屬性(attribute)。
注意:IE7不支持該方法。
自定義屬性data-*
html5里有一個data-*去設置獲取元素的自定義屬性值。
利用div1.dataset可以獲得一個DOMStringMap,包含了元素的所有data-*。
使用div1.dataset.aa就可以獲取11的值。
同樣,通過設置div1.dataset.bb = "22"就可以設置一個自定義屬性值。
在不兼容的瀏覽器里,就使用getAttribute和setAttributevar div1 = document.getElementById("div1"); var a = null; if (div1.dataset) { a = div1.dataset.aa; div1.dataset.bb = "222"; } else { a = div1.getAttribute("data-aa"); div1.setAttribute("data-bb", "2222"); } console.log(a);7.事件addEventListener()
addEventListener()將指定的事件監(jiān)聽器注冊到目標對象上,當目標對象觸發(fā)制定的事件時,指定的回調函數就會觸發(fā)。目標對象可以是 文檔上的元素、 document、 window 或者XMLHttpRequest(比如onreadystatechange事件)。
IE8及以下不支持此方法且只有事件冒泡沒有事件捕獲。IE9開始支持此方法,也就有了事件捕獲。
var div1 = document.getElementById("div1"); div1.addEventListener("click", listener, false); function listener() { console.log("test"); } var cloneHtml = div1.cloneNode(true); document.body.appendChild(cloneHtml);第一個參數是事件名,第二個是回調函數,第三個參數為true表示捕獲,false表示冒泡。
var div1 = document.getElementById("div1"); div1.addEventListener("click", listener1, true/fasle); function listener1() { console.log("test1"); } var div2 = document.getElementById("div2"); div2.addEventListener("click", listener2, true/fasle); function listener2() { console.log("test2"); }有一點要注意的是,當對某一個元素1既綁定了捕獲事件,又綁定了冒泡事件時:
當這個元素1并不是觸發(fā)事件的那個元素2時,則觸發(fā)順序會按照先 捕獲 后 冒泡 的順序觸發(fā);
當這個元素1就是最底層的觸發(fā)事件的元素時,則這個元素沒有捕獲和冒泡的區(qū)別,誰先綁定就先觸發(fā)誰。var div2 = document.getElementById("div2"); div2.addEventListener("click", listener2, true); function listener2() { console.log("test2"); } div2.addEventListener("click", listener1, false); function listener1() { console.log("test1"); } // 按綁定順序執(zhí)行,兩個`addEventLister()`顛倒過來則執(zhí)行順序也變化 // 如果再對`div1`綁定一個捕獲、一個冒泡,則會先觸發(fā)捕獲 再 觸發(fā)冒泡,與綁定順序無關removeEventListener()
與addEventListener()綁定事件對應的就是移除已綁定的事件。第三個參數的布爾值代表解綁的是捕獲事件還是冒泡事件。兩個事件互不相關。
var div2 = document.getElementById("div2"); div2.addEventListener("click", listener2, true); function listener2() { console.log("test2"); } div2.removeEventListener("click", listener2, true);注意:只能通過removeEventListener()解綁有名字的函數,對于綁定的匿名函數無法解除綁定。
div2.addEventListener("click", function(){ console.log("test"); console.log(this); }, true); div2.removeEventListener("click", function() { console.log("test"); }, true); div2.onclick = null; // 點擊div2依然打印出test注意:這里this指向觸發(fā)事件的元素自身。
attachEvent()、detachEvent()
IE8及以下使用這兩個方法綁定和解綁事件,當然,IE9+也支持這個事件。但這個方法綁定的事件默認為冒泡也只有冒泡。
// 這里需要在事件前加 on div2.attachEvent("onclick", listener1); function listener1() { console.log("test"); console.log(this); } div2.detachEvent("onclick", listener1);和addEventListener()一樣,也不能解綁匿名函數。
注意:這里this指向 window。阻止默認事件和冒泡
標準事件和IE事件中的阻止默認事件和冒泡事件也有很大區(qū)別。
var div2 = document.getElementById("div2"); if (div2.addEventListener) { div2.addEventListener("click", function(e) { e.preventDefault(); // 阻止默認事件 e.stopPropagation(); // 阻止冒泡 console.log(e.target.innerHTML); }, false); } else { div2.attachEvent("onclick", function() { var e = window.event; e.returnValue = false; // 阻止默認事件 e.cancelBubble = true; // 阻止冒泡 console.log(e.srcElement.innerHTML); }); }IE8及以下的event是綁定在window上的。(我的IE11里,仿真到IE7、IE8也可以取到標準事件里的 e 對象,估計是升級到IE11的原因)。
自定義事件:createEvent()
createEvent()用于創(chuàng)建一個新的 event ,而后這個 event 必須調用它的 init() 方法進行初始化。最后就可以在目標元素上使用dispatchEvent()調用新創(chuàng)建的event事件了。
createEvent()的參數一般有:UIEvents、MouseEvents、MutationEvents、HTMLEvents、Event(s)等等,分別有對應的init()方法。HTMLEvents、Event(s)對應的都是initEvent()方法。
initEvent(type, bubbles, cancelable)type表示自定義的事件類型,bubbles表示是否冒泡,cancelable表示是否阻止默認事件。
target.dispatchEvent(ev)target就是要觸發(fā)自定義事件的DOM元素
var div1 = document.getElementById("div1"); div1.addEventListener("message", function(){ console.log("test"); }, false); var div2 = document.getElementById("div2"); div2.addEventListener("message", function(e){ console.log(this); console.log(e); }, false); var ev = document.createEvent("Event"); ev.initEvent("message", false, true); // 起泡參數變?yōu)閠rue,div1的事件就會觸發(fā) div2.dispatchEvent(ev);8.獲取元素相關計算后的值getComputedStyle()、currentStyle()
當我們想獲取元素計算后實際呈現(xiàn)在頁面上的各個值,就用這兩個方法。IE8及以下用currentStyle(),IE9+及其他標準瀏覽器用getComputedStyle()。
var div2 = document.getElementById("div2"); var result = ""; if (window.getComputedStyle) { result = (window || document.defaultView).getComputedStyle(div2, null)["cssFloat"]; } else { result = div2.currentStyle["styleFloat"]; } console.log(result); // document.defaultView返回document對象所關聯(lián)的window這兩個方法在不同的瀏覽器里差距也很大。
比如float屬性:
getComputedStyle: IE9以上需要用cssFloat,其他標準的用float
currentStyle: IE8及以下可用styleFloat或者float。比如height屬性:
假如未設置height值,標準瀏覽器里能計算出高度值,而currentStyle計算出來是auto。上面的例子getComputedStyle是用鍵值去訪問的,也可用getPropertyValue()去訪問。(IE8、IE7不支持)
result = (window || document.defaultView).getComputedStyle(div2, null).getPropertyValue("float");getBoundingClientRect()、getClientRects()
getBoundingClientRect()該方法獲得頁面中某個元素的上、右、下、左分別相對瀏覽器視窗的位置。getBoundingClientRect是DOM元素到瀏覽器可視范圍的距離(到瀏覽器頂部而不是文檔頂部)。該函數返回一個Object對象,該對象有6個屬性:top,lef,right,bottom,width,height;這里的top、left和css中的理解很相似,width、height是元素自身的寬高,但是right,bottom和css中的理解有點不一樣。right是指元素右邊界距窗口最左邊的距離,bottom是指元素下邊界距窗口最上面的距離。
getClientRects()是返回一個ClientRectList集合。
var div1 = document.getElementById("div1"); var rects1 = div1.getClientRects(); var rects2 = div1.getBoundingClientRect(); console.log(rects1[0].top); console.log(rects2.top);文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78243.html
摘要:作為運行在瀏覽器中的腳本語言,它對于網頁操作非常有用。在技術圈中,我們將這些指令稱為操作。結論文檔對象模型是瀏覽器創(chuàng)建并保留在內存中的網頁的虛擬副本。資源如果你想了解更多關于文檔對象模型的內容,那么還有另一篇好文章。 翻譯:瘋狂的技術宅原文:https://www.valentinog.com/bl... showImg(https://segmentfault.com/img/bV...
摘要:前言終于要做這個計劃了,前端框架千千萬,絕不能一頭扎進去盲目開始,本片文章總結一下目前前各種端框架,以及它們的用途主要解決什么問題,然后最后做出學習計劃。希望入了前端坑的同學們可以有所幫助。但是庫與框架很難嚴格區(qū)分,所以統(tǒng)一稱為解決方案。 前言:終于要做這個計劃了,前端框架千千萬,絕不能一頭扎進去盲目開始,本片文章總結一下目前前各種端框架,以及它們的用途主要解決什么問題,然后最后做出學...
摘要:年,和前端開發(fā)者與應用程序前端開發(fā)者之間產生了巨大的分歧。開發(fā)最常見的解決方案有手機和平板的原生應用程序桌面應用程序桌面應用程序原生技術最后,前端開發(fā)者可以從瀏覽器開發(fā)中學習到,編寫代碼不需要考慮瀏覽器引擎的限制。 前端開發(fā)者手冊2019 Cody Lindley 編著 原文地址 本手冊由Frontend Masters贊助,通過深入現(xiàn)代化的前端工程課程來提高你的技能。 下載:PDF ...
摘要:年,和前端開發(fā)者與應用程序前端開發(fā)者之間產生了巨大的分歧。開發(fā)最常見的解決方案有手機和平板的原生應用程序桌面應用程序桌面應用程序原生技術最后,前端開發(fā)者可以從瀏覽器開發(fā)中學習到,編寫代碼不需要考慮瀏覽器引擎的限制。 前端開發(fā)者手冊2019 Cody Lindley 編著 原文地址 本手冊由Frontend Masters贊助,通過深入現(xiàn)代化的前端工程課程來提高你的技能。 下載:PDF ...
摘要:年,和前端開發(fā)者與應用程序前端開發(fā)者之間產生了巨大的分歧。開發(fā)最常見的解決方案有手機和平板的原生應用程序桌面應用程序桌面應用程序原生技術最后,前端開發(fā)者可以從瀏覽器開發(fā)中學習到,編寫代碼不需要考慮瀏覽器引擎的限制。 前端開發(fā)者手冊2019 Cody Lindley 編著 原文地址 本手冊由Frontend Masters贊助,通過深入現(xiàn)代化的前端工程課程來提高你的技能。 下載:PDF ...
摘要:為什么會慢呢因為對的修改為影響網頁的用戶界面,重繪頁面是一項昂貴的操作。太多的操作會導致一系列的重繪操作,為了確保執(zhí)行結果的準確性,所有的修改操作是按順序同步執(zhí)行的。回流操作主要會發(fā)生在幾種情況下當對節(jié)點執(zhí)行新增或者刪除操作時。 一. 函數式編程 React 把用戶界面抽象成一個個組件,如按鈕組件 Button、對話框組件 Dialog、日期組件 Calendar。 開發(fā)者通過組...
閱讀 2296·2023-04-25 16:42
閱讀 1202·2021-11-22 14:45
閱讀 2338·2021-10-19 13:10
閱讀 2827·2021-09-29 09:34
閱讀 3408·2021-09-23 11:21
閱讀 2100·2021-08-12 13:25
閱讀 2180·2021-07-30 15:15
閱讀 3491·2019-08-30 15:54