HTML 頁面中顯示 XML 數據
在下面的實例中,我們打開一個 XML 文件("cd_catalog.xml"),然后遍歷每個 CD 元素,并顯示HTML 表格中的 ARTIST 元素和 TITLE 元素的值:
實例
<html>
<body>
<script>
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("GET","cd_catalog.xml",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;
document.write("<table border='1'>");
var x=xmlDoc.getElementsByTagName("CD");
for (i=0;i<x.length;i++)
{
document.write("<tr><td>");
document.write(x[i].getElementsByTagName("ARTIST")[0].childNodes[0].nodeValue);
document.write("</td><td>");
document.write(x[i].getElementsByTagName("TITLE")[0].childNodes[0].nodeValue);
document.write("</td></tr>");
}
document.write("</table>");
</script>
</body>
</html>
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
內容是《Web前端開發之Javascript視頻》的課件,請配合大師哥《Javascript》視頻課程學習。
Document 接口描述了任何類型的文檔的通用屬性與方法,根據不同的文檔類型(例如HTML、XML)提供了不同的API,比如,使用 "text/html" 作為內容類型的HTML文檔,實現了 HTMLDocument,而XML文檔則實現了XMLDocument,HTMLDocument和XMLDocument接口都是繼承自Document接口;
Javascript通過Document類型表示文檔;在瀏覽器中,document對象是Document的一個實例,更具體一點,是HTMLDocument的一個實例,其表示整個HTML頁面;并且document對象也是window對象的一個屬性,可以將其作為全局對象來訪問;因此document對象,既屬于BOM又屬于DOM的對象;
Document節點的特征:
其子節點可能是一個DocumentType(最多一個)、Element(最多一個,即html)、ProcessingInstruction或Comment;
console.log(document); // 在FF控制臺可以看出是屬于HTMLDocument類型
console.log(document.nodeType); // 0
console.log(document.nodeName); // #document
console.log(document.nodeValue); // null
console.log(document.parentNode); // null
console.log(document.childNodes.length); // 2
文檔的子節點:
DOM標準規定Document節點的子節點可以是DocumentType、Element、ProcessingInstruction或Comment;
<!-- 這是一個comment -->
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<script>
console.log(document.childNodes); // 使用FF查看 NodeList(3)
</script>
</body>
</html>
documentElement屬性:
返回文檔直接子節點,始終指向HTML頁面中的<html>元素,也就是文檔的根元素,并且它一定是文檔的根元素;
// 注意:在HTML中的第二行有可能是注釋
console.log(document.childNodes[2]); // <html>
console.log(document.documentElement); // <html>
console.log(document.lastChild); // <html>
借助這個只讀屬性,能方便地獲取到任意文檔的根元素;
body屬性:
作為HTMLDocument的實例,document對象還有一個body屬性,直接指向<body>;
console.log(document.body);
對于一個擁有<frameset>元素的文檔來說,返回的是最外層的<frameset>元素;
另外,該屬性是可寫的,且為該屬性賦的值必須是一個<body>元素;
// 如果HTML結構為body id="oldBody",則:
console.log(document.body.id); // oldBody
var newBody = document.createElement("body");
newBody.id = "newBody";
document.body = newBody;
console.log(document.body.id); // newBody
head屬性:
指向<head>元素,這個Document對象擴展的一個屬性,類型為HTMLHeadElement;
如果有多個<head>元素,則返回第一個;
document.head 是個只讀屬性,為該屬性賦值只會靜默失敗,如果在嚴格模式中,則會拋出TypeError異常;
需要注意的是,如果文檔源代碼中未顯式的包含<head>和<body>元素,瀏覽器將隱式的創建它們;
doctype屬性:
該屬性是DocumentType 類型,表示了一個包含文檔類型的節點對象,指向<!DOCTYPE>標簽;
文檔當中最多只有一個DocumentType元素;
console.log(document.doctype); // <!DOCTYPE html>
console.log(document.doctype.nextSibling); // <html>
console.log(document.childNodes[0]); // <!DOCTYPE html>
如果存在文檔聲明,則將其作為document的第一個子節點,解析DOCUMENTTYPE_NODE類型,如果沒有聲明,則為null;
注:DocumentType對象不能動態創建,它是只讀的;
查找元素(選取文檔元素):
在DOM中,取得特定的某個或某組元素,并執行一些操作,這是最重要的應用了;
為了獲取文檔中的這些元素Element對象,DOM定義了許多方式,如:用指定的id屬性、name屬性、標簽名、CSS類或CSS選擇器;
取得元素的操作可以使用document對象的幾個方法來完成;Document類型為此提供了兩個方法;
getElementById()方法:
該方法接收一個參數,即要獲取的元素的ID;如果找到就返回這個元素,類型是HTMLElement,如果不存在,則返回null;該參數ID是區分大小寫的;
如果頁面中多個元素的ID值相同,只返回文檔中第一次出現的元素;
var mydiv = document.getElementById("mydiv");
console.log(mydiv);
可以封裝一個通過ID查找多個元素的函數,如:
/**
* 函數接受任意多的字符串參數
* 返回一個對象
* 如果一個id對應的元素未定義,則拋出錯誤
*/
function getElements(/*ids...*/){
var elements = {}; // 一個空map映射對象
for(var i=0; i<arguments.length; i++){
var id = arguments[i];
var elt = document.getElementById(id);
if(elt == null)
throw new Error("No element with id:" + id);
elements[id] = elt;
}
return elements;
}
console.log(getElements("mydiv","mylist"));
console.log(getElements("mydiv","mylist")["mydiv"]);
getElementById方法不會搜索不在文檔中的元素;當創建一個元素,并且分配ID后,必須要使用appendChild、insertBefore等方法把元素插入到文檔中,之后才能使用getElementById()方法獲取到;
var elt = document.createElement("div");
elt.id = "myelt";
document.body.appendChild(elt); // myelt,添加到文檔對后,才能被獲取到到
var el = document.getElementById("myelt");
console.log(el); // null
getElementsByName()方法:
返回給定name 屬性的所有元素NodeList集合對象;
var mytexts = document.getElementsByName("mytext");
console.log(mytexts); // dom2.html:17 NodeList(2) [p, div]
該方法定義在HTMLDocument類中,而不在Document類中,所以它只針對HTML文檔可用,也就是只有HTMLDocument類型才有的方法,在XML文檔中不可用;
<fieldset>
<legend>選擇你最喜歡的城市</legend>
<ul>
<li><input type="radio" value="北京" name="city" id="beijing" />
<label for="beijing">北京</label></li>
<li><input type="radio" value="南京" name="city" id="nanjing" />
<label for="nanjing">南京</label></li>
<li><input type="radio" value="蚌埠" name="city" id="bengbu" />
<label for="bengbu">蚌埠</label></li>
</ul>
</fieldset>
<script>
var citys = document.getElementsByName("city");
console.log(citys);
</script>
該方法返回的是NodeList對象,在NodeList中返回的元素按照在文檔中的順序排序的,所以可以使用方括號語法來取得每個元素;
console.log(document.getElementsByName("city")[0]);
但IE與Edge返回的是HTMLCollection;但namedItem()方法是屬于HTMLCollection類型的,所以,非IE調用namedItem()方法會拋出異常;并且在IE中namedItem()只會返回第一項,因為每一項的name特性都是相同的;
console.log(citys.namedItem("city"));
為某些HTML元素設置name屬性,將自動在windows對象中創建對應的屬性,對Document對象也是類似的;比如,為<form>、<img>、<iframe>、<applet>、<embed>或<object>元素設置name屬性,即在Document對象中創建以此name屬性值為名字的屬性;
<form name="myform"></form>
<script>
console.log(document.myform);
</script>
即使如此,建議不要用這種方式來獲取元素,最好還是顯式的使用getElementsByName()方法;
getElementsByTagName()方法:
該方法是通過標簽名來獲取元素,其接收一個參數,即要取得元素的標簽名;返回擁有零個或多個元素的HTMLCollection集合對象,其是動態集合,與NodeList非常類似;;
var spans = document.getElementsByTagName("span");
console.log(spans); // HTMLCollection
其擁有length屬性,可以通過方括號或者item()方法來訪問HTMLCollection對象中的項;還擁有一個namedItem()方法,該方法可以通過元素的name屬性取得集合中的項,但可以簡寫為使用方括號訪問;即如果是數值,則調用item(),如果是字符串索引,就調用namedItem();
var divs = document.getElementsByTagName("div");
console.log(divs);
console.log(divs[0]);
console.log(divs.item(1));
console.log(divs.namedItem("innerDiv"));
console.log(divs["innerDiv"]);
console.log(images[0].src);
images.item(1).src = "images/3.jpg";
如果傳入“*”,則取得頁面中所有元素;(在JS和CSS中,*就是匹配所有的通配符);
var nodes = document.getElementsByTagName("*");
console.log(nodes);
會打印出頁面中所有的元素,按照它們出現的順序(沒有層次之分);
在HTML中,該方法參數不需要區分大小寫,而在XML中,區分大小寫;
Element類也定義了getElementsByTagName()方法,其原理和Document一樣,但是它只選取調用該方法的元素的后代元素;
var mydiv = document.getElementById("mydiv");
// 也可以通過getElementsByTagName來獲取
// var mydiv = document.getElementsByTagName("div")[0];
var spans = mydiv.getElementsByTagName("span");
console.log(spans);
文檔信息:
作為HTMLDocument的一個實例,document對象還有一些標準的Document對象所沒有的屬性;這些屬性提供了document對象所表現的網頁的一些信息;
從BOM角度來看document對象是window對象的屬性,由一系列集合構成,這些集合可以訪問文檔的各個部分,并提供頁面自身的信息,可以認為document即為加載的html文檔;
document.title:包含著<title>元素中的文本,通過它,可以獲取或修改當前頁面的標題;
var originalTitle = document.title;
console.log(originalTitle);
document.title = "zeronetwork title";
// 標題跑馬燈效果
var str="北京零點網絡科技有限公司-";
document.title = str;
function titleMove(){
str = str.substring(1,str.length) + str.substring(0,1);
document.title = str;
}
setInterval("titleMove()",1000);
lastModified:返回文檔被最后修改的日期和時間;
cookie:允許Javascript讀寫的HTTP cookie的特殊屬性;
location:與window對象的location屬性引用同一個Location對象;
URL:包含頁面完整的URL;一般情況下,該屬性的值與location.href 屬性相同;但不包含Location對象的動態變化,即在 URL 重定向發生的時候,這個URL屬性保存了文檔的實際URL,不會發生變化,而 location.href會發生變化;location.href 是可寫的,document.URL是只讀的;
console.log(document.URL);
console.log(location.href);
document.URL = "demo.html"; // 無效
console.log(document.URL);
// location.href = "demo1.html"; // 跳轉
referrer:來源頁面的URL(鏈接到當前頁面的那個頁面),如果沒有來源,referrer為空字符串;該屬性是只讀的;
console.log(document.referrer);
這個屬性在分析網站SEO數據時特別有用;
var referrer = document.referrer;
var origin = location.origin;
console.log(referrer);
console.log(origin);
if(referrer){
if(referrer.indexOf(origin) == 0){
document.write("站內瀏覽");
}else{
document.write("從外鏈:" + referrer + "進入");
}
}else{
document.write("直接打開");
}
查找搜索關鍵詞:
var ref = document.referrer;
console.log(ref);
if(ref.indexOf("http://127.0.0.1:5500/search.html?") == 0){
var args = ref.substring(ref.indexOf("?") + 1).split("&");
for(var i=0; i<args.length; i++){
if(args[i].substring(0,2) == "q="){
document.write("<h2>搜索的是:</h2>");
keys = args[i].substring(2).split("+");
for(var k in keys){
document.write(decodeURIComponent(keys[k]) + "<br>");
}
break;
}
}
}
domain屬性:獲取或設置當前文檔的域名;
該屬性允許當Web頁面之間交互時,相同域名下互相信任的Web服務器之間協作放寬同源策略安全限制,其是可讀的,但有安全限制,即不能為domain賦任意值;
不能將該屬性設置為URL中不包含的域;
// FF提示“The operation is insecure.”,Chrome提示不是127.0.0.1的子域名
// document.domain = "www.zeronetwork.cn"; // 異常
console.log(document.domain);
document對象的集合:
除了屬性和方法,document對象還有一些特殊的集合;這些集合都是HTMLCollection對象,為訪問文檔的常用部分提供了快捷方式,包括:
document.anchors:包含文檔中所有帶name特性的<a>元素;這個屬性已經從Web標準中刪除了,但瀏覽器還支持,所以盡量不要再使用;
<!-- link.html頁面 -->
<h1>零點程序員</h1>
<h2><a name="one">Web前端開發</a></h2>
<div style="height: 1000px;background-color: purple;">DIV</div>
<h2><a name="two">后端開發</a></h2>
<div style="height: 1000px;background-color: green;">DIV</div>
<h2><a name="three">蘋果開發</a></h2>
<div style="height: 1000px;background-color: blue;">DIV</div>
<!-- 主頁面 -->
<p>
<input type="button" value="Web前端開發" onclick="jump('one')" />
<input type="button" value="后端開發" onclick="jump('two')" />
<input type="button" value="蘋果開發" onclick="jump('three')" />
</p>
<script>
var win = window.open("link.html","newWin","width=250,height=150");
function jump(name) {
console.log(name);
if(win.document.anchors[name]){
win.location.hash = name;
win.focus();
}else{
alert("錨不存在")
}
}
</script>
document.links:包含文檔中所有帶href特性的<a>元素或<area>元素;
var mydiv = document.getElementById("mydiv");
var links = document.links;
for(var i=0,len=links.length; i<len; i++){
var aNode = document.createElement("a");
aNode.href = links[i].href;
var href = document.createTextNode(links[i].innerText);
aNode.appendChild(href);
mydiv.appendChild(aNode);
}
打開外鏈進行提醒:
var links = document.links;
for(var i=0,len=links.length; i<len; i++){
var link = links[i];
link.addEventListener("click",function(e){
e.preventDefault();
if(e.target.host !== location.host)
jump(e.target.innerText, e.target.href);
else
location.href = e.target.href;
},false);
}
function jump(title,href){
var div = document.createElement("div");
div.id = "jumpDiv";
document.body.appendChild(div);
var str = document.createTextNode("你要訪問的:" + href + "不屬于本網站,你要繼續訪問嗎?");
div.appendChild(str);
var aGo = document.createElement("a");
aGo.href = href;
aGo.target = "_blank";
aGo.appendChild(document.createTextNode("繼續"));
div.appendChild(aGo);
var aBack = document.createElement("a");
aBack.href = "Javascript:void(0);";
aBack.appendChild(document.createTextNode("關閉"));
aBack.onclick = closeJumpDiv;
div.appendChild(aBack);
}
function closeJumpDiv(){
var jumpDiv = document.getElementById("jumpDiv");
if(jumpDiv)
jumpDiv.parentNode.removeChild(jumpDiv);
}
document.applets:包含文檔中所有的<applet>元素;
document.forms:包含文檔中所有的<form>元素,與document.getElementsByTagName(“form”)得到的結果是相同的;
<form name="myform">
<!-- id也可為以-->
<input type="text" id="username" />
</form>
<form name="yourform"></form>
<script>
console.log(document.forms); // HtmlCollection
console.log(document.forms.myform);
console.log(document.forms[0]);
console.log(document.forms["myform"]);
console.log(document.forms.myform.username);
</script>
document.embeds:包含文檔中所有的<embeds>元素;
document.plugins:包含文檔中所有的插件;注意和navigator.plugins的區別;
console.log(document.plugins); // HTMLCollection
console.log(navigator.plugins); // pluginArray
document.images:包含文檔中所有的<img>元素實時集合,集合中的每個元素代表了一個image元素的HTMLImageElement,與document.getElementsByTagName(“img”)得到的結果是相同的;
document.scripts:返回一個HTMLCollection對象,包含了當前文檔中所有<script>元素的集合;
document.all:只讀屬性,返回一個HTMLAllCollection,包含了頁面上的所有元素;已從Web標準中刪除,但是瀏覽器都支持,但建議不要使用;與document.getElementsByTagName(“*”)得到的結果基本相同的;
console.log(document.all); // HTMLAllCollection
console.log(document.getElementsByTagName("*")); // HTMLCollection
console.log(document.all[9]);
document.all[9].innerHTML = "零點程序員";
// id或name為"mydiv"的元素,但是有區別的,為name的元素只是插入text
document.all["mydiv"].innerHTML = "<h2>零點程序員</h2>";
以上這些集合始終都可以通過HTMLDocument對象訪問到,而且,它們都是動態的;但現在已經被 document.getElementsByTagName()所取代,部分已經廢棄不應該再使用,但是仍然常常被使用,因為他們使用起來很方便;
文檔寫入:
document對象,可以將文本字符串寫入文檔流中;
write()與writeln()方法:
這兩個都接受一個字符串參數,即要寫入到輸出流中的文本;write()會原樣寫入,writeln()則會在字符串的末尾添加一個換行符(\n);
這兩個方法會將其字符串參數連接起來,然后將結果字符串插入到文檔中調用它們的腳本元素的位置;
document.write("<h1>" + document.title + "</h1>");
document.write("<strong>" + (new Date()).toString() + "</strong>");
不光輸出內容,還會解析為DOM元素;
參數可以是多種形式,如:
// 部分替換為writeln()方法
var username = "wangwei";
document.write("我的名字:" + username + "<br/>");
document.write("sum:" + (5 + 4));
document.write("<ul>");
document.write("<li>HTML</li>","<li>CSS</li>","<li>Javasc </li>");
document.write("</ul>")
var arr = ["<p>zeronetwork</p>","<p>wangwei</p>","<p>web</p>"];
document.write(arr.join(""));
function func(){
return "func";
}
document.write(func + "<br>");
document.write(function(){
return "Happy";
}());
只有在解析文檔時才能使用write()方法輸出HTML到當前文本,如果把write()方法放到一個函數內或者在文檔加載結束后再調用document.write(),那么輸出的內容將會重寫整個頁面;如:
window.onload = function(){
document.write("零點程序員");
}
這里有個問題,理論上來說,重寫了整個頁面后,原頁面中的所有變量和值都應該被清除,但事實卻不是這樣的,IE是這樣的行為,但其他瀏覽器會保留原內容中的變量和值;
var num = 10;
function fun(){
document.write("fun");
}
var mydiv = document.getElementById("mydiv");
window.onload = function(){
document.write("重寫了整個頁面");
console.log(num);
fun();
document.body.appendChild(mydiv);
}
正因為它們不兼容,所以不要在新文檔流中調用原內容中的變量和值;
open()與close()方法:
可以使用write()方法在其他的窗口或框架頁中來創建整個全新文檔,但一般會配合close和open方法一起使用;
open()和close()分別用于打開和關閉網頁的輸出流;如果是在頁面加載期間使用write()或writeln()方法,則不需要用到這兩個方法,因為文檔此時是打開狀態;向一個已經加載完成的文檔寫入數據時,會自動調用 document.open,并且會擦除該文檔的所有內容,因為已經加載完成的文檔,它的文檔流已經關閉,就是已經自動調用了document.close();
可以多次調用write()來逐步建立新文檔的內容;傳遞給write的內容可能緩存起來,所以一旦完成了數據寫入,建議調用 document.close()來結束該寫序列,以告訴HTML解析器,文檔已經達到了文件的末尾,寫入的數據會被解析到文檔結構模型(DOM)里,此時應該結束解析并顯示新文檔;
btn.onclick = function(){
document.open(); // 可以省略
document.write("重寫了整個頁面");
document.close();
}
此時,如果在close()方法后,再調用write()方法就會重寫整個新窗口的內容,如:
// 在onclick事件處理函數中繼續添加
document.write("文檔又被重寫了");
注意:無法關閉系統創建的文檔流,如果,我們在全局環境中直接執行close()方法,會發現沒有效果,原因就是無法關閉系統創建的文檔流,我們只能關閉自己打開的文檔流;
在新窗口也是同樣的道理;
var oNewWin=window.open("about:blank","newwindow","width=400,width=200");
oNewWin.document.open();
oNewWin.document.write("<h1>新窗</h1>");
oNewWin.document.write("<div>這是一個新窗口</div>");
oNewWin.document.close();
在使用write()方法時,最好一次性寫入;
<input type="button" id="btn" value="寫入">
<script>
var newWin = null;
function makeNewWin(){
newWin = window.open("about:blank","newWin","width=400,height=300");
}
var btn = document.getElementById("btn");
btn.onclick = function(){
// 如果newWin不存在或已關閉,再次打開
if(!newWin || newWin.closed)
makeNewWin();
newWin.focus();
var title = "零點程序員";
var newStr = "<!DOCTYPE html>";
newStr += "<html><head>";
newStr += "<title>" + title + "</title></head>";
newStr += "<body>";
newStr += "<h1>零點程序員</h1>";
newStr += "<div>這是內容</div>";
// 把body拆分成</b和ody>,否則會拋出異常
newStr += "</b" + "ody></html>";
newWin.document.write(newStr);
newWin.document.close();
}
</script>
document.open()另類的用法:
2個參數的open()方法,語法為document.open(type, replace),如:
document.open("text/html","replace");
type指定了所需寫入的數據的MIME類型,默認值為”text/html”,replace(如有設置,值為一個字符串“replace”)指定了新文檔從父文檔繼承歷史條目;
使用open()方法,在IE中會產生歷史條目,其他瀏覽器不會產生,因此這種用法只會在IE中有效果;而如果指定了replace參數,IE就不會產生歷史條目,也就是父文檔的記錄被覆蓋了;
這種形式現在已經棄用;
3個參數的open()方法,是Window.open()的一個別名;
var doc = document.open("https://www.zeronetwork.cn/","","width=400;");// 打開新窗口
console.log(doc); // Window
doc.document.write("<h1>零點程序員</h1>"); // 重寫
doc.document.close();
// doc.close(); // 會關閉窗口
動態加載外部資源:
使用write()和writeln()兩個方法,還可以動態加載外部資源,如Javascript文件等,但要注意,不能直接包含字符串“</script>”,因為會導致代碼不能正確的解析;
document.write("<script type=\"text/javascript\" src=\"file.js\">" + "<\/script>");
// 或者
document.write("<script type=\"text/javascript\" src=\"file.js\">" + "</scr" + "ipt>");
這種方法經常在廣告和統計功能的第三方中使用;
為什么不直接使用<script>標簽,而直接使用動態載入呢?原因有兩個:
一是腳本的URL不能寫死,比如要動態添加一些參數,用戶設備的分辨率啊,當前頁面 URL 啊,防止緩存的時間戳之類的,這些參數只能先用 JS 獲取到,再比如國內常見的網站統計代碼:
<script>
var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");
document.write(unescape("%3Cspan id='cnzz_stat_icon_1279580898'%3E%3C/span%3E%3Cscript src='" +
cnzz_protocol + "s9.cnzz.com/stat.php%3Fid%3D1279580898' type='text/javascript'%3E%3C/script%3E"));
</script>
它之所以使用write()方法,而不使用<script>元素,就是為了先用 JS 判斷出該用http還是https 協議;
另外,有可能需要在腳本里加載另外一個腳本文件或嵌入的JS內容有可能會修改頁面內容,而這些操作只需要第三方自己維護,不需要自己的網站去維護;
在實際開發中,write()并不常用,innerHTML屬性和其他DOM技術提供了更好的方法來為文檔增內容;比如,可以利用innerHTML來輸出內容:
var mydiv = document.getElementById("mydiv");
mydiv.innerHTML = "<h1>零點程序員</h1><p>開設了Web前端課程</p>";
// 重寫body內所有內容
document.body.innerHTML = "<h1>零點程序員</h1><p>開設了Web前端課程</p>";
包裝一個對象,類似于write()和close()方法:
// 為設置元素的innerHTML定義簡單的"流式"API
function ElementStream(elt){
if(typeof elt === "string")
elt = document.getElementById("elt");
this.elt = elt;
this.buffer = "";
}
// 連接所有的參數,添加到緩存中
ElementStream.prototype.write = function(){
this.buffer += Array.prototype.join.call(arguments, "");
};
// 類似write(),只是多增加了換行符
ElementStream.prototype.writeln = function(){
this.buffer += Array.prototype.join.call(arguments, "") + "\n";
};
// 從緩存設置元素的內容,然后清空緩存
ElementStream.prototype.close = function(){
this.elt.innerHTML = this.buffer;
this.buffer = "";
}
var mydiv = document.getElementById("mydiv");
var elt = new ElementStream(mydiv);
elt.write("<h1>零點程序員</h1>");
elt.writeln("<p>王唯</p>");
elt.close();
Web前端開發之Javascript-零點程序員-王唯
內容是《Web前端開發之Javascript視頻》的課件,請配合大師哥《Javascript》視頻課程學習。
Element類型用于表示XML或HTML元素,提供了對元素標簽名、子節點及特性的訪問;
Element類繼承自Node接口;它繼承了Node接口中的所有屬性和方法,比如parentNode、childNode等;同時,它在Node接口的基礎上擴展了自己的屬性和方法;
Element類型的特征:
var mydiv = document.getElementById("mydiv");
console.log(mydiv.nodeType); // 1
console.log(mydiv.nodeName); // DIV
console.log(mydiv.nodeValue); // null
console.log(mydiv.parentNode); // <body>
console.log(mydiv.childNodes); // NodeList
Element的屬性:
id屬性:表示元素的標識符,與全局屬性id對應;
var mydiv = document.getElementById("mydiv");
console.log(mydiv.id);
mydiv.id = "yourdiv";
console.log(mydiv.id);
var yourdiv = document.getElementById("yourdiv");
console.log(yourdiv.id);
tagName屬性:與nodeName屬性一樣,可以返回元素的標簽名,在HTML文檔中返回大寫,在XML中返回原生,因此在使用tagName時,最后使用toLowerCase()轉換;
var mydiv = document.getElementById("mydiv");
console.log(mydiv.tagName); // DIV
if(mydiv.tagName.toLowerCase() == "div"){
//...
}
一般使用tagName,因為從字義上理解更加清晰;
Element的子類型HTMLElement:
HTMLElement類型直接繼承自Element,因此,HTML元素即屬于HTMLElement類也屬于Element類;
所有HTML元素都由HTMLElement類型或其子類型表示,比如:HTMLDIVElement,就是具體的div元素的類型;
HTMLElement類型在Element類的基礎上,并添加了一些屬性,這些屬性分別對應于每個HTML元素中都存在的標準特性:id、title、lang、dir、className;
這些屬性都是可讀可寫的,并且也是動態的;
<div id="mydiv" name="mydiv" title="DIV" lang="en" dir="ltr" class="divclass">
// …
<script>
var mydiv = document.getElementById("mydiv");
console.log(mydiv.id);
console.log(mydiv.title);
console.log(mydiv.lang);
console.log(mydiv.dir);
console.log(mydiv.className);
mydiv.id = "yourdiv";
mydiv.title = "你的DIV";
mydiv.lang = "fr";
mydiv.dir = "rtl";
mydiv.className = "reddiv";
</script>
Element特性(屬性):
每個元素都有若干個特性,這些特性的用途是給出相應元素或其內容的附加信息;DOM為Element對象定義了一些API來獲取或設置這些XML或HTML屬性(特性);
操作特性主要有三個方法:
getAttribute()、setAttribute()、removeAttribute();這些方法可以針對任何特性使用,包括那些以HTMLElement類型屬性的形式定義的特性;
getAttribute(attributeName)方法:
返回元素上一個指定的特性值,如果指定的特性不存在,則返回null或 "";特性的名稱不區分大小寫;
如果取得class,需要傳入class,而不是className;
var mydiv = document.getElementById("mydiv");
console.log(mydiv.getAttribute("id")); // mydiv
console.log(mydiv.getAttribute("class")); // divclass
console.log(mydiv.getAttribute("title")); // null
也可以取得自定義特性(即不是HTML元素的標準特性),但要注意,根據HTML5的規范,自定義特性應該加上data-前綴以便驗證;
console.log(mydiv.getAttribute("custom")); // customvalue
console.log(mydiv.getAttribute("data-name")); // wangwei
任何元素的所有特性,都可以通過DOM元素本身的屬性來訪問,不過,只有公認的(非自定義)特性才會以屬性的形式添加到DOM對象中;但IE可以為自定義特性創建屬性;
console.log(mydiv.id);
console.log(mydiv.className);
console.log(mydiv.myname); // undefined
console.log(mydiv.align); // left,認為align是公認的
var img = document.getElementById("myimg");
var imgurl = img.src;
console.log(img.id === "myimg");
var f = document.forms[0];
f.action = "https://www.zeronetwork.cn/do.php";
f.method = "POST";
HTML屬性名不區分大小寫,但Javascript屬性名則大小寫敏感;從HTML屬性名轉換到Javascript屬性名應該采用小寫,但是如果屬性名包含不止一個單詞,則采用小駝峰式,如:defaultCheded和tabIndex;
有些HTML屬性名在Javascript中是保留字,對于這些屬性,一般的規則是為該屬性名加前綴”html”,如,HTML的for屬性在Javascript中變為htmlFor屬性,class屬性比較特殊,它在Javascript中變成className屬性;
表示HTML屬性的值通常是字符串,但當屬性為布爾值或數值時,Javascript中對應的屬性也是布爾值或數值,而不是字符串;
<label id="lbInput" for="txtInput">文本框:</label>
<input id="txtInput" tabindex="2" type="text" readonly />
<script>
var txtInput = document.getElementById("txtInput");
console.log(txtInput.tabIndex); // 1
console.log(txtInput.readOnly); // true
var lbInput = document.getElementById("lbInput");
console.log(lbInput.htmlFor); // txtInput
</script>
style和事件處理程序特性:
style:在通過getAttribute()訪問時,返回的style特性值中包含的是CSS文本;而通過屬性訪問它會返回一個CSSStyleDeclaration對象(由于style屬性是用于以編程方式訪問元素樣式的對象,因此并沒有直接映射到style特性,有關CSS編程,后面我們會講到);
事件處理程序特性,類似于onclick等這樣的事件處理程序,當在特性中使用時,onclick中包含的就是JS代碼,使用getAttribute()會返回相應的代碼的字符串,但在訪問onclick屬性時,會返回一個Javascript函數;
var mydiv = document.getElementById("mydiv");
console.log(mydiv.getAttribute("style")); // font-size: 14px;color:red;
console.log(mydiv.style); // CSSStyleDeclaration or CSS2Properties
console.log(mydiv.getAttribute("onclick")); // alert('zeronetwork');
console.log(mydiv.onclick); // function onclick(event)
setAttribute(name, value)方法:
設置指定元素上的某個特性值,如果特性已經存在,則更新該值,否則,使用指定的名稱和值添加一個新的特性;
該接受兩個參數:要設置的特性名和值;
此方法可以操作HTML特性也可以操作自定義特性;
var mydiv = document.getElementById("mydiv");
mydiv.setAttribute("id","outerdiv");
mydiv.setAttribute("class","outerdivclass");
mydiv.setAttribute("title","mydiv title");
mydiv.setAttribute("style","border-bottom:1px solid;color:purple;");
mydiv.setAttribute("custom","custom value");
console.log(mydiv.title); // mydiv title
console.log(mydiv.custom); // undefined
通過該方法設置的特性名會被統一轉換成小寫形式,即“ID”最終會變成“id”;
mydiv.setAttribute("ID","myID"); // id
mydiv.setAttribute("CID","customID"); // cid
布爾特性只要出現在元素上就會被認為是 true,無論它的值是什么;一般來說,應該將 value 設置為空字符串,也有人使用這個屬性的名稱作為值,雖然不會出現什么問題,但不規范的;
var txtInput = document.getElementById("txtInput");
txtInput.setAttribute("readonly",true);// 會渲染成readonly="true"
txtInput.setAttribute("readonly",""); // 渲染成readonly
console.log(txtInput.readOnly); // true
因為所有特性都是屬性,所以直接給屬性賦值可以設置特性的值,但如果添加的是一個自定義的屬性,該屬性不會自動成為元素的特性;
mydiv.title = "mydiv title";
mydiv.style = "border-bottom:1px solid;color:purple;";
mydiv.custom = "custom value"; // html中并沒有渲染custom
console.log(mydiv.title); // mydiv title
console.log(mydiv.custom); // custom value
console.log(mydiv.getAttribute("title")); // mydiv title
console.log(mydiv.getAttribute("custom")); // null
可以通過setAttribute()方法設置class,但不能通過屬性設置class,因為class是關鍵字,需要className進行屬性設置;
var mydiv = document.getElementById("mydiv");
mydiv.setAttribute("class","att_class");
// mydiv.class = "att_class"; // 無效,class是保留字
mydiv.className = "att_class";
console.log(mydiv.class); // undefined
console.log(mydiv.className); // att_class
removeAttribute(attrName)方法:
用于從指定的元素徹底刪除元素的特性;
此方法不僅會清除特性的值,而且也會從元素中完全刪除特性;
此方法并不常用,但在序列化DOM元素時,可以通過它來確切地指定要包含哪些特性;
var mydiv = document.getElementById("mydiv");
mydiv.removeAttribute("class");
mydiv.removeAttribute("style");
mydiv.setAttribute("custom","custom_value");
mydiv.removeAttribute("custom");
mydiv.title = "mydiv title";
mydiv.removeAttribute("title");
hasAttribute(attrName)方法和hasAttributes()方法:
用于檢測特性是否存在;其中hasAttribute()需要一個特性參數,判斷該元素是否包含有指定的特性,而hasAttributes()檢測的是否有特性,具體是什么特性,則不是它所關心的了;
var mydiv = document.getElementById("mydiv");
console.log(mydiv.hasAttribute("title"));
if(!mydiv.hasAttribute("align"))
mydiv.setAttribute("align","center");
console.log(mydiv.hasAttributes()); // true
當屬性為布爾值時,hasAttribute()方法特別有用,比如HTML表單的disabled屬性,只要判斷它有沒有這個屬性即可,不用管它的值;
attributes屬性:
返回該元素所有屬性節點的一個實時集合,該集合是一個NamedNodeMap對象,是一個只讀的類數組對象,只有Element類型擁有;該屬性與NodeList類似,也是一個動態的集合;也可以使用索引方式訪問,并且可以枚舉;
元素的每個特性都由一個Attr節點表示,Attr對象是一個特殊的Node,不會像普通的Node一樣去使用;Attr的name和value屬性返回該屬性的名字和值;
每個Attr節點都保存在NamedNodeMap對象中;此節點都有nodeName、nodeValue等屬性,nodeName就是特性的名稱,nodeValue就是特性的值;
var mydiv = document.getElementById("mydiv");
console.log(mydiv.attributes);
console.log(mydiv.attributes[1]);
console.log(mydiv.attributes.title);
console.log(mydiv.attributes.custom);
mydiv.attributes.title = "wangwei"; // 無效
console.log(mydiv.attributes[1].nodeType); // ATTRIBUTE_NODE
console.log(mydiv.attributes[1].nodeName);
console.log(mydiv.attributes[1].nodeValue);
NamedNodeMap對象:
表示一個無順序的屬性節點 Attr 對象的集合;其是類數組對象,同時也是動態的;
屬性和方法:
length屬性:返回映射(map)中對象的數量;
getNamedItem(name):返回給定名稱name的屬性節點;
item(pos):返回位于數字pos位置處的節點;(注:各個瀏覽器會返回不同的順序);
setNamedItem(node):向列表中添加或替換特性節點;
removeNamedItem(name):從列表中移除特性為name的節點;與removeAttribute()相同,但其會返回被刪除的特性(Attr)節點;
可以通過attributes屬性使用方括號直接訪問特性;
var mydiv = document.getElementById("mydiv");
console.log(mydiv.attributes);
console.log(mydiv.attributes.item(1));
console.log(mydiv.attributes.getNamedItem("name"));
console.log(mydiv.attributes[1]);
console.log(mydiv.attributes["name"]);
mydiv.attributes["id"].nodeValue = "newID";
mydiv.attributes.getNamedItem("name").nodeValue = "newName";
var deleteStyle = mydiv.attributes.removeNamedItem("style");
console.log(deleteStyle);
var yourdiv = document.getElementById("yourdiv");
yourdiv.attributes.setNamedItem(deleteStyle);
var attr = document.createAttribute("dir");
attr.nodeValue = "ltr";
mydiv.attributes.setNamedItem(attr);
使用attributes屬性較麻煩,因此使用getAttribute()、removeAttribute()和removeAttribute()方法比較常用;但在遍歷元素的特性時,attributes屬性比較方便;
遍歷attributes屬性:
在需要將DOM結構序列化為XML或HTML字符串時,多數都會涉及遍歷元素特性;
// 迭代元素的所有特性,構造成name=”value” name=”value”這樣的字符串格式
var mydiv = document.getElementById("mydiv");
function outputAttributes(element){
var pairs = new Array();
for(var attr in element.attributes){
if(element.attributes[attr] instanceof Attr){
// console.log(attr + element.attributes[attr]);
var attrName = element.attributes[attr].nodeName;
var attrValue = element.attributes[attr].nodeValue;
// console.log(attrName);
pairs.push(attrName + "=\"" + attrValue + "\"");
}
}
// 或者使用for循環
// for(var i=0,len=element.attributes.length; i<len; i++){
// var attrName = element.attributes[i].nodeName;
// var attrValue = element.attributes[i].nodeValue;
// // console.log(attrName);
// pairs.push(attrName + "=\"" + attrValue + "\"");
// }
return pairs.join(" ");
}
console.log(outputAttributes(mydiv));
創建Element元素:
document.createElement(tagName)方法:用于創建一個由標簽名稱tagName指定的HTML元素,如果用戶代理無法識別tagName,則會生成一個未知 HTML 元素;
該方法只接受一個參數,即要創建元素的標簽名;此標簽名在HTML中不區分大小寫,在XML(包括XHTML)中,是區分大小寫的;
在創建新元素的同時,也為新元素設置了ownerDocument屬性;同時還可以操作元素的特性,為它添加子節點,以及執行其他操作;
新創建的元素,必須添加到文檔樹中,才能顯示出來,可以利用appendChild,insertBefore()或replaceChild()方法;
var div = document.createElement("div");
div.innerHTML = "<h2>零點程序員</h2>";
div.id = "outerDiv";
div.className = "outerDiv";
div.setAttribute("style","color:green;");
console.log(div.ownerDocument);
document.body.appendChild(div);
var h3 = document.createElement("h3");
h3.setAttribute("onclick","alert('this is zeronetwork');");
h3.innerText = "zeronetwork";
div.insertBefore(h3, null);
Element的子節點:
元素可以有任意數目的子節點和后代節點,這些子節點可能是元素、文本、注釋處處理指令;但HTML中的空白也會被解析為文本節點;因此在執行某項操作時,要先檢查一下nodeType屬性;
<!-- 結構 -->
<ul id="myList">
<li>HTML</li>
<li>CSS</li>
<li>Javascript</li>
</ul>
<!-- 或者刪除空白 -->
<ul id="myList"><li>HTML</li><li>CSS</li><li>Javascript</li></ul>
// js代碼
var myList = document.getElementById("myList");
console.log(myList.childNodes.length);
for(var i=0,len=myList.childNodes.length; i<len; i++){
if(myList.childNodes[i].nodeType == Node.ELEMENT_NODE)
console.log(myList.childNodes[i].nodeName);
}
// 或者
// for(var n in myList.childNodes){
// if(myList.childNodes[n].nodeType && myList.childNodes[n].nodeType == Node.ELEMENT_NODE)
// console.log(myList.childNodes[n].nodeName);
// }
元素節點也支持getElementsByTagName() 方法,可以通過它獲得某個特定的標簽名的子節點或后代節點;
var myList = document.getElementById("myList");
var lis = myList.getElementsByTagName("li");
console.log(lis); // dom.html:23 HTMLCollection(3)
自定義Element的方法:
Element和HTMLDocument等類型都像String和Array一樣是類,它們不是構造函數,但它們有原型對象,可以自定義方法擴展它;
Element.prototype.next = function(){
if(this.nextElementSibling) return this.nextElementSibling;
var sib = this.nextSibling;
while(sib && sib.nodeType !== 1) sib = sib.nextSibling;
return sib;
}
console.log(document.getElementById("mydiv").next());
Web前端開發之Javascript-零點程序員-王唯
*請認真填寫需求信息,我們會在24小時內與您取得聯系。