首頁>技術>

本內容是《Web前端開發之Javascript影片》的課件,請配合大師哥《Javascript》影片課程學習。

DocumnetTyp型別:

包含著與文件的doctype有關的所有資訊,被儲存在document.doctype物件中;

該型別繼承自Node類;

特徵:

nodeType的值為10;nodeName的值為doctype的名稱;nodeValue的值為null;parentNode是Document;沒有子節點;
console.log(document.doctype);  // <!DOCTYPE html>console.log(document.doctype.nextSibling); // <html>console.log(document.doctype.nodeType);  // 10 DOCUMENTTYPE_NODE型別console.log(document.doctype.nodeName);  // htmlconsole.log(document.doctype.nodeValue);  // nullconsole.log(document.doctype.parentNode);  // #documentconsole.log(document.childNodes);  console.log(document.childNodes[0]); // <!DOCTYPE html>

DOM1級中,DocumentType物件不能動態建立,而只能透過解析文件的方式來建立;並把DocumentType物件儲存在document.doctype中;

DOM1描述瞭解DocumentType物件的3個屬性:

name:表示文件型別的名稱,即出現在<!DOCTYPE之後的文字;

console.log(document.doctype.name);  // html

entities:是由文件型別描述的實體的NamedNodeMap物件;

notations:是由文件型別描述的符號的NamedNodeMap物件

entities和notations均為NamedNodeMap型別,一般在XML中使用,在HTML中entities和notations都是空列表,所以通常為null或undefined;

DocumentFragment型別:

文件片段型別,在所有節點型別中,只有它在文件中沒有對應的標識;

DOM規定文件片段(document fragment)稱為“輕量級”的文件,它是一種特殊的Node,作為其他節點的臨時的容器,可以包含和控制節點,但不會像完整的文件那樣佔用額外的資源;

特徵:

nodeType的值為11;nodeName的值為#document-fragment;nodeValue的值為null;parentNode的值為null;

雖然文件片段就跟標準的document一樣,裡面儲存了由節點組成的文件結構,但因為文件片段是獨立的,不屬於文件的一部分,所以它的parentNode總是為null,並且,它的變化不會觸發DOM樹的重新渲染,也不會導致效能等問題;

文件片段的子節點可以是Element、ProcessingInstruction、Comment、Text、CDATASection或Entity-Reference;

文件片段型別本身沒有定義屬性和方法,其繼承了Node的所有方法,通常用於執行那些針對文件的DOM操作;主要用其來儲存將來可能會新增到文件中的節點;

利用document.createDocumentFragment()方法建立片段;

var fragment = document.createDocumentFragment();console.log(fragment);console.log(fragment.nodeType);  // 11console.log(fragment.nodeName);  // #document-fragmentconsole.log(fragment.nodeValue);  // nullconsole.log(fragment.parentNode);  // nullconsole.log(fragment.childNodes);  // NodeList

另外,其提供了文件片段的建構函式DocumentFragment(),使用它也可以返回一個文件片段物件,但IE不支援;

var fragment = new DocumentFragment();

可以透過appendChild()或insertBefore()將文件片段中的內容新增到文件中,同時,文件片段被清空;

<ul id="myList"></ul><script>var myList = document.getElementById("myList");var fragment = document.createDocumentFragment();for(var i=0; i<3; i++){    var li = document.createElement("li");    li.appendChild(document.createTextNode("課程:" + (i + 1)));    fragment.appendChild(li);}myList.appendChild(fragment);// 或者var courseArr = ["HTML","CSS","Javascript"];var fragment = document.createDocumentFragment();courseArr.forEach(function(c){    var li = document.createElement("li");    li.innerHTML = c;    fragment.appendChild(li);});myList.appendChild(fragment);</script>

如:倒序排列一個節點的子節點:

function reverse(node){    var fragment = document.createDocumentFragment();    // 從後至前迴圈子節點,將每個子節點移動到文件片段中    // 如此,node的最後一個節點變成fragment的第一個節點    while(node.lastChild)        fragment.appendChild(node.lastChild);    // 把fragment的所有子節點一次性移加node中    node.appendChild(fragment);}var mylist = document.getElementById("mylist");reverse(mylist);

文件片段其實在一個叫<template>元素中特別有用,該元素屬於HTMLTemplateElement型別,其有個content 屬性,就包含了一個DocumentFragment;只是可惜IE不支援;

在瀏覽器中會被渲染成

<template id="courseList">    #document-fragment</template> --><template id="courseList">    <h2>Web前端開發</h2>    <ul>        <li>HTML</li>        <li>CSS</li>        <li>Javascript</li>    </ul></template><script>var courseList = document.getElementById("courseList");console.log(courseList.content);  // #document-fragmentvar p = document.createElement("p");p.innerHTML = "該課程由大師哥王唯主講";courseList.content.appendChild(p);document.body.appendChild(courseList.content);</script>

Attr型別:

元素的特性在DOM中以Attr型別表示,就是存在於元素的attributes屬性中的節點;其繼承自Node類;儘管它也是節點,但特性卻不被認為是DOM文件樹的一部分;

特徵:

nodeType的值2;nodeName的值為特性的名稱;nodeValue的值就是特性的值;parentNode的值為null;在HTML沒有子節點;在XML中子節點可以是Text或EntityReference;
var mydiv = document.getElementById("mydiv");var attr = mydiv.getAttributeNode("name");console.log(attr);console.log(attr.nodeType); // 2console.log(attr.nodeName);  // nameconsole.log(attr.nodeValue);  // mydivconsole.log(attr.parentNode);  // null

Attr物件有3個屬性:

name、value和specified;

console.log(attr.name);  // nameconsole.log(attr.value);  // mydivconsole.log(attr.specified);  // true

Attr物件的相關方法:

document.createAttribute(name)方法:

建立並返回特性節點,傳入特性的name名稱;建立後可以透過為該節點的nodeValue屬性設定該屬性節點的屬性值,也可以使用常用的 setAttribute()方法來替代該方法;

var attr = document.createAttribute("style");attr.nodeValue = "color:red;";

setAttributeNode(attribute)方法:

為指定的Element新增屬性節點,注意,該法是Element元素方法;建立特性節點後,必須使用元素的setAttributeNode()方法將特性節點新增到元素特性中;該方法會返回一個Attr屬性節點;

var stylArr = mydiv.setAttributeNode(attr);

該特性物件不能被複用,一旦被新增到某個元素特性中,其他元素就不能再使用,但可以克隆,如:

var h2 = document.getElementsByTagName("h2")[0];// h2.setAttributeNode(attr);  // 異常h2.setAttributeNode(attr.cloneNode());

這個方法很少使用,一般都是使用setAttribute()方法;

getAttributeNode(attrName)方法:返回指定元素的指定Attr節點;

用以上方法新增Attr節點後,可以透過attributes屬性,getAttributeNode()方法,getAttribute()方法來訪問;其中,attributes和getAttributeNode()會返回對應特性的Attr節點,而getAttribute()返回特性的值;

var mydiv = document.getElementById("mydiv");var attr = document.createAttribute("style");attr.nodeValue = "font-size:20px; color: blue;";mydiv.setAttributeNode(attr);console.log(mydiv.getAttribute("style"));console.log(mydiv.getAttributeNode("style"));console.log(mydiv.getAttributeNames());

這個方法也很少使用,一般使用getAttribute()方法;

var delAttr = mydiv.removeAttributeNode(attr);console.log(delAttr);console.log(attr);console.log(delAttr === attr);// 注意,要先註釋前面幾行if(mydiv.hasAttribute("style")){    var delAttr = mydiv.getAttributeNode("style");    delAttr = mydiv.removeAttributeNode(delAttr);    console.log(delAttr);}

一般最常使用的是getAttribute()、setAttribute()和removeAttribute()方法,很少直接引用特性節點;

NodeList及HTMLCollection:

getElementsByName()返回的是NodeList,getElementsByTagName()返回是的HTMLCollection,document物件的集合也是HTMLCollection型別的;

理解NodeList及NamedNodeMap和HTMLCollection,是從整體上透徹理解DOM的關鍵所在;

這些物件都是類陣列物件,都有length屬性,也可以像真正的陣列一樣索引,但只能讀不能寫;

forEach():迭代;IE不支援;

nodelist.forEach(function(v,k,p){    console.log(v);});

但可以藉助陣列的forEach()方法;

Array.prototype.forEach.call(nodelist, function(v,k,p){    console.log("k:" + k, "v:" + v, "p:" + p);});

HTMLCollection介面屬性和方法:

length:只讀,返回集合中子元素的數目;

item():根據給定的索引,返回具體的節點;如果索引超出了範圍,則返回 null;

namedItem():根據Id或name返回指定節點,根據name匹配只能作為後備,並且只有當被引用的元素支援name屬性時才能被匹配,如果不存在符合給定name的節點,則返回null;

NodeList和HTMLCollection介面都定義了item()方法,接收一個整數,返回此索引處的元素;在實際開發中,沒有必要使用這個方法,因為直接使用索引顯得更加簡單;

HTMLCollection定義了namedItem()方法,返回指定屬性名的值,但也不常用,因為也是可以直接使用索引或常規屬性來訪問;

以上三個集合都是“動態的”,換句話說,每當文件結構發生變化時,它們都會得到更新;因此,它們始終都會儲存著最新、最準確的資訊;

從本質上說,所有NodeList物件都是在訪問DOM文件時實時執行的查詢;

如,以下程式碼會導致無限迴圈:

var divs = document.getElementsByTagName("div"),    i,    div;for(i=0; i<divs.length; i++){    div = document.createElement("div");    document.body.appendChild(div);}

如果想要迭代一個NodeList,最好是使用length屬性初始化第二個變數,然後將迭代器與該變數進行比較,如:

var divs = document.getElementsByTagName("div"),    i,    len,    div;for(i=0, len=divs.length; i<len; i++){    div = document.createElement("div");    document.body.appendChild(div);}

或者直接對NodeList和HTMLCollection物件生成一個副本,在副本上進行一系列操作;

var snapshot = Array.prototype.slice.call(nodelist,0);

不要使用for...in或者for each...in來遍歷一個NodeList物件中的元素,因為它們會把NodeList 物件中的 length 和 item 屬性也遍歷出來,這可能會導致指令碼執行出錯;此外,for...in也不能保證訪問這些屬性的順序;

一般來說,應該儘量減少訪問NodeList的次數,因為每次訪問NodeList,都會執行一次基於文件的查詢,所以,從一開始,可以將NodeList中取得的值快取起來,然後再使用;

但NodeList也並不總是動態的,比如document.querySelectorAll就會返回一個靜態 NodeList;

12
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • springboot呼叫k8s配置中心apollo-含原始碼