天天看點

Js DOM學習筆記--回顧

      去年寒假在家看完了JavaScpript DOM這本書 剛清理電腦資料的時候發現了這個學習筆記資料 就順便上傳了 如有錯誤 一起交流 ,一起進步

前半部分摘自

W3school 還可以直接參考 http://www.w3school.com.cn/htmldom/index.asp

下面分割線後為dom學習筆記

JS和DOM關系

js 即 JavaScript ,是一種網頁腳本語言,可以在網頁上實作一些動态效果。  
DOM 是HTML文檔結構,其實就是為了能讓js操作html元素而制定的一個規範,  
dom 的根本就是 document 對象,改對象有很多屬性和方法,  
例如建立節點、複制節點、移除節點、修改屬性等。
           

我們用JavaScript對網頁進行的所有操作都是通過DOM進行的。DOM屬于浏覽器,而不是JavaScript語言規範裡的規定的核心内容

HTML DOM (文檔對象模型)

當網頁被加載時,浏覽器會建立頁面的文檔對象模型(Document Object Model)。

HTML DOM 模型被構造為對象的樹。 來看一下關系樹形圖:

此圖來自:

http://www.w3school.com.cn/js/js_htmldom.asp

通過可程式設計的對象模型,JavaScript 獲得了足夠的能力來建立動态的 HTML。

JavaScript 能夠改變頁面中的所有 HTML 元素
JavaScript 能夠改變頁面中的所有 HTML 屬性
JavaScript 能夠改變頁面中的所有 CSS 樣式
JavaScript 能夠對頁面中的所有事件做出反應           

注意:

js和html分離很重要

屬性: display:inline;可以實作清單橫向顯示

外部引用css

<link rel="stylesheet" href="styles/layout.css" type="text/css"  
 media="screen">           

document.write() 可用于直接向 HTML 輸出流寫内容。

<!DOCTYPE html>
<html>
<body>

<script>
document.write(Date());
</script>

</body>
</html>           

提示:絕不要使用在文檔加載之後使用 document.write()。這會覆寫該文檔。

修改 HTML 内容的最簡單的方法時使用 innerHTML 屬性。

如需改變 HTML 元素的内容,請使用這個文法:

document.getElementById(id).innerHTML=new HTML

改變了标簽元素 元素的内容:

<html>
<body>

<p id="p1">Hello World!</p>

<script>
document.getElementById("p1").innerHTML="New text!";
</script>

</body>
</html>           
<!DOCTYPE html>
<html>
<body>

<h1 id="header">Old Header</h1>

<script>
var element=document.getElementById("header");
element.innerHTML="New Header";
</script>

</body>
</html>           

改變 HTML 屬性

document.getElementById(id).attribute=new value
<!DOCTYPE html>
<html>
<body>

<img id="image" src="smiley.gif">

<script>
document.getElementById("image").src="landscape.jpg";
</script>

</body>
</html>           

改變 HTML 樣式

document.getElementById(id).style.property=new style
<p id="p2">Hello World!</p>

<script>
document.getElementById("p2").style.color="blue";
</script>           

使元素不可見和可見

<!DOCTYPE html>
<html>
<body>

<p id="p1">這是一段文本。</p>

<input type="button" value="隐藏文本" onclick="document.getElementById('p1').style.visibility='hidden'" />
<input type="button" value="顯示文本" onclick="document.getElementById('p1').style.visibility='visible'" />

</body>
</html>
           
本例改變了 id="id1" 的 HTML 元素的樣式,當使用者點選按鈕時:

<h1 id="id1">My Heading 1</h1>

<button type="button" onclick="document.getElementById('id1').style.color='red'">
點選這裡
</button>           

對事件做出反應:

onclick=JavaScript

當使用者點選滑鼠時
當網頁已加載時
當圖像已加載時
當滑鼠移動到元素上時
當輸入字段被改變時
當送出 HTML 表單時
當使用者觸發按鍵時           

栗子:

<h1 onclick="this.innerHTML='謝謝!'">請點選該文本</h1>           
<!DOCTYPE html>
<html>
<head>
<script>
function changetext(id)
{
id.innerHTML="謝謝!";
}
</script>
</head>
<body>
<h1 onclick="changetext(this)">請點選該文本</h1>
</body>
</html>           

使用 HTML DOM 來配置設定事件

HTML DOM 允許您通過使用 JavaScript 來向 HTML 元素配置設定事件:

<script>
document.getElementById("myBtn").onclick=function(){displayDate()};
</script>           

在上面的例子中,名為 displayDate 的函數被配置設定給 id=myButn” 的 HTML 元素。

當按鈕被點選時,會執行該函數。

<!DOCTYPE html>
<html>
<head>
</head>
<body>

<p>點選按鈕就可以執行 <em>displayDate()</em> 函數。</p>

<button id="myBtn">點選這裡</button>

<script>
document.getElementById("myBtn").onclick=function(){displayDate()};
function displayDate()
{
document.getElementById("demo").innerHTML=Date();
}
</script>

<p id="demo"></p>

</body>
</html> 
           

onload 和 onunload 事件會在使用者進入或離開頁面時被觸發。

onload 事件可用于檢測通路者的浏覽器類型和浏覽器版本,并基于這些資訊來加載網頁的正确版本。

onload 和 onunload 事件可用于處理 cookie。

<!DOCTYPE html>
<html>
<body onload="checkCookies()">

<script>
function checkCookies()
{
if (navigator.cookieEnabled==true)
    {
    alert("已啟用 cookie")
    }
else
    {
    alert("未啟用 cookie")
    }
}
</script>

<p>提示框會告訴你,浏覽器是否已啟用 cookie。</p>
</body>
</html>
           

onchange 事件

onchange 事件常結合對輸入字段的驗證來使用。

下面是一個如何使用 onchange 的例子。當使用者改變輸入字段的内容時,會調用 upperCase() 函數。

<!DOCTYPE html>
<html>
<head>
<script>
function myFunction()
{
var x=document.getElementById("fname");
x.value=x.value.toUpperCase();
}
</script>
</head>
<body>

請輸入英文字元:<input type="text" id="fname" onchange="myFunction()">
<p>當您離開輸入字段時,會觸發将輸入文本轉換為大寫的函數。</p>

</body>
</html>           

onmouseover 和 onmouseout 事件

onmouseover 和 onmouseout 事件可用于在使用者的滑鼠移至 HTML 元素上方或移出元素時觸發函數。

<!DOCTYPE html>
<html>
<body>

<div onmouseover="mOver(this)" onmouseout="mOut(this)" style="background-color:green;width:120px;height:20px;padding:40px;color:#ffffff;">把滑鼠移到上面</div>

<script>
function mOver(obj)
{
obj.innerHTML="謝謝"
}

function mOut(obj)
{
obj.innerHTML="把滑鼠移到上面"
}
</script>

</body>
</html>
           

onmousedown、onmouseup 以及 onclick 事件

onmousedown, onmouseup 以及 onclick 構成了滑鼠點選事件的所有部分。首先當點選滑鼠按鈕時,會觸發 onmousedown 事件,當釋放滑鼠按鈕時,會觸發 onmouseup 事件,最後,當完成滑鼠點選時,會觸發 onclick 事件。

<!DOCTYPE html>
<html>
<body>

<div onmousedown="mDown(this)" onmouseup="mUp(this)" style="background-color:green;color:#ffffff;width:90px;height:20px;padding:40px;font-size:12px;">請點選這裡</div>

<script>
function mDown(obj)
{
obj.style.backgroundColor="#1ec5e5";
obj.innerHTML="請釋放滑鼠按鈕"
}

function mUp(obj)
{
obj.style.backgroundColor="green";
obj.innerHTML="請按下滑鼠按鈕"
}
</script>

</body>
</html>           

當輸入字段獲得焦點時,改變其背景色。

<!DOCTYPE html>
<html>
<head>
<script>
function myFunction(x)
{
x.style.background="yellow";
}
</script>
</head>
<body>

請輸入英文字元:<input type="text" onfocus="myFunction(this)">

<p>當輸入字段獲得焦點時,會觸發改變背景顔色的函數。</p>

</body>
</html>
           

當指針移動到元素上方時,改變其顔色;當指針移出文本後,會再次改變其顔色。

<!DOCTYPE html>
<html>
<body>

<h1 onmouseover="style.color='red'" onmouseout="style.color='blue'">
請把滑鼠移到這段文本上
</h1>

</body>
</html>
           

建立新的 HTML 元素

如需向 HTML DOM 添加新元素,您必須首先建立該元素(元素節點),然後向一個已存在的元素追加該元素。

<!DOCTYPE html>
<html>
<body>

<div id="div1">
<p id="p1">這是一個段落。</p>
<p id="p2">這是另一個段落。</p>
</div>

<script>
var para=document.createElement("p");
var node=document.createTextNode("這是新段落。");
para.appendChild(node);

var element=document.getElementById("div1");
element.appendChild(para);
</script>

</body>
</html>
           

删除已有的 HTML 元素

如需删除 HTML 元素,您必須首先獲得該元素的父元素:

<!DOCTYPE html>
<html>
<body>

<div id="div1">
<p id="p1">這是一個段落。</p>
<p id="p2">這是另一個段落。</p>
</div>

<script>
var parent=document.getElementById("div1");
var child=document.getElementById("p1");
parent.removeChild(child);
</script>

</body>
</html>
           

提示:如果能夠在不引用父元素的情況下删除某個元素,就太好了。

不過很遺憾。DOM 需要清楚您需要删除的元素,以及它的父元素。

這是常用的解決方案:找到您希望删除的子元素,然後使用其 parentNode 屬性來找到父元素:

var child=document.getElementById("p1");
child.parentNode.removeChild(child);           

注意點: title是滑鼠移到上面顯示的内容 alt是圖檔加載不出來顯示的内容

為了減少對網站的請求次數 應該将.js檔案合并到一個檔案中

事件處理函數 如 onclick(“show(this);xx();”) 裡面包涵多個js語句的時候 用分号隔開

1.對象有内建對象和宿主對象 内建對象包括Array數組 Math Date 這些都是預定義好的對象 可以直接拿來使用

宿主對象是由他的運作環境提供的,再Web應用中 這個環境就是浏覽器 宿主對象包括 Form Image 和Element等等擷取關于網頁上表單,圖像和各種表格元素的資訊

還有一個比較重要的對象是doucumet 可以擷取網頁上任何元素的資訊。

節點是網絡中的一個連接配接點 一個網絡就是由一些節點構成的集合 元素節點裡面的屬性就是屬性節點 内容就是 文本節點

css中還有繼承 比如定義了body的标簽的css 則該css還将作用于鑲嵌在body元素内部的所有元素

擷取元素 文檔中每一個元素都是一個對象。 元素類型由typeof顯示出來的都是object

1. document.getElementById(“”);

2. document.getElementsByTagName(“”) 傳回的是一個對象數組 就算這個标簽隻有一個元素 也會傳回一個數組 長度可以用屬性length來通路

可以用var items=document.getElementsByTagName(“”) 這樣可以省點力氣 以後 items[1]就是document.getElementByTagName(“”)[1]

舉個例子:

var shopping=document.getElementById("purchses");
     var items=shopping.getElementsByTagName("*");           
  1. getElementsByClassName(“”) 是得到 含有相同類名的數組

    還可以找到那些帶多個類名的元素 比如 getElementByClassName(“xx yy”) 表示這個數組找到的元素中 class同時帶有 xx和yy的類名

    xx和yy的順序無所謂 yy和xx也會被找到 而且 類名隻要包涵xx和yy 還有其他類名的也會被找出來

    var shopping=document.getElementById(“purchses”);

    * var items=shopping.getElementsByClassName(“xx yy”);*

    這樣就得到了 id=purchses中的 帶有xx和yy類的元素

    這個 方法比較有用 但是隻有較新的浏覽器才支援他

盤點知識點:   一份文檔就是一顆節點樹  節點包括元素節點 屬性節點 文本節點
每一個節點都是一個對象
.getElementById傳回一個對象
 getElementsByClassName(“”)和getElementByTagName("")傳回一個數組元素節點的子節點是文本節點  元素節點的nodeValue是null值 而元素節點的子結點的第一個節點就是文本節點
 元素節點.childNodes[0].nodeValue才是元素節點的文本節點
           

擷取屬性:

getAttribute(“”)參數是要查詢屬性的名字 可以配合 getElementById來使用 直接後面.getAttribute 如果沒有該屬性 會傳回 null或者空白

取決于用哪種浏覽器

通過 if(xx.getAttribute(“title”)) 來判斷有無這個屬性

setAttribut(“xx”,”yy”) xx是标簽名 yy是要修改的内容 如果事先不存在xx這個屬性 則先建立xx這個屬性 然後再指派 如果存在就覆寫掉

需要注意的是 它源代碼顯示的還是修改前的屬性值 這是“表裡不一” 對頁面内容進行重新整理但是不需要在浏覽器裡重新整理頁面

getElementById
getElementsByClassName
getElementsByTagName
getAttribute    得到節點的屬性
setAttribute    修改節點的屬性
           

舉個例子:

var shopping=document.getElementById("xx");
var name=shopping.getAttribute("title");
shopping.setAttribute("title","wocaonima");           

實作一個 在一個網頁裡 點選超連結 就可以在指定的圖檔位置更換圖檔:

function showPic(a)
{
    var source=a.getAttribute("href");
    var palceer=document.getElementById("xx");
    palceer.setAttribute("src",source);
}           

重點:

再給元素添加事件處理函數後 一旦事件觸發 js代碼會傳回一個布爾值 如果是true表示成功觸發 false表示出發失敗

比如 onclick=”showPic(this);” 表示 showPic函數被調用 預設行為也會被調用 意味着 使用者還是被帶到圖檔檢視視窗 為了阻止這個預設行為被

調用 可以 這樣修改

onclick="showPic(this);return false;"           

window.onload是當文檔加載完成後才會執行時間處理函數。

綁定一個匿名函數

<script type="text/javascript">
    window.onload=function(){
        document.getElementById("big").style=...
    }
</script>
<script type="text/javascript">
    window.onload=function myalert()}
        alert("sdf");
    }
    }
</script>           

childNodes是得到元素下的子節點 可是 文檔中的每一個東西都是一個節點包括空格

這時候需要nodeType屬性來判别了 node.nodeType

元素節點:nodeType屬性值是1
屬性節點:                2
文本節點:                3           

這樣就可以隻針對特定節點進行操作

<script type="text/javascript">
    function xx(){
        var body_number=document.getElementsByTagName("body")[0];
        alert(body_number.childNodes.length);
    }
window.onload=xx;
</script>           

nodeValue是文本節點的值

還有 firstChild和lastChild屬性

node.firstChild 等效于node.childNodes[0]

node.lastChild 等效于 node.childNodes[node.childNodes.length-1]

舉例子:

function showPic(xx){
    var source=xx.getAttribute("href");
    var placer=document.getElementById("yy");
    palcer.setAttribut("src",source);
    var text=xx.getAttribute("title");
    var description=document.getElementById("description");
    description.firstChild.nodeValue=text;
}           

總結 :

childNodes  得到子節點
   nodeType    子節點類型
   nodeValue   節點的文本節點值
   firstChild  第一個子節點
   lastChild   最後一個子節點           
<script type="text/javascript">
    function popUp(winURL){
        window.open(winURL,"name","width=320,height=480");
    }
 </script>

  1.<a href="javascript:popUp('www.baidu.com');">xxx</a>
  "javascript:"是僞協定 
  2.内嵌:   <a href="#" onclick="popUp('www.baidu.com');return false;"> sdf</a>  href是為了建立一個空連結,實際工作全部由onclick屬性負責完成           

return false 是取消這個連接配接的預設行為,不讓這個連結把通路者帶離目前視窗

但是缺點是 不能平穩退化 意思就是說 使用者如果禁用了浏覽器的javascript功能 這樣的連結将毫無用處

getElementById 為此 可以這樣改進:

<a href="www.baidu.com" onclick="popUp(this.href);return false;"> sdf</a>            

但是這個也有缺點因為它沒有打開一個新的視窗(js失效的話)

css可以實作結構和樣式的分離

這樣可以確定網頁能平穩退化

我們也可以分離js 将如下代碼加入到外部js檔案中去

成功将行為和結構分離的例子

window.onload=pre;
   function pre(){
    var links=document.getElementByTagName("a");
    for(var i=0;i<links.length;i++) {
        if(links[i].getAttribute("class")=="popup") {
            links[i].onclick=function(){
                popUp(this.getAttribute("href"));
                return false;
            }
        }
    }
   }
   function popUp(winURL){
        window.open(winURL,"name","width=320,height=470");
   }
           

對象檢測

添加if(!document.getElementById) return false; 對于不支援這個函數的浏覽器 仍可以通路網頁的内容

注意:盡量減少通路DOM和盡量減少标記

把 <script>放在文檔的末尾 可以讓網頁變得更快           

壓縮腳本可以使網頁加載更快 可以使用工具 比如 變量 var dection 改成 var a 是以工作的時候 一般應該有兩個版本 一個工作副本用來修改代碼并添加注釋 另一個是精簡版本 用于放在站點

為了區分 最好在精簡版本的檔案名中加上min字樣 比如: scriptName.min.js

代碼壓縮工具: 谷歌的Closure Compiler

平穩退化

分離JS

向後相容

性能考慮

改進版:

之前圖庫中每個超連結标簽a中都需要class來挂鈎把js和html中有關的标記關聯起來 現在隻需要定義一個挂鈎 在清單 那 ul添加一個 id就可以了

注意:不應該讓js代碼對這個頁面結構有任何依賴 如上面的例子 如果将圖庫删除 js就出錯了

是以可以這樣子

if(!document.getElementById){
        return false;
   }   這是普遍做法  getElementById後面不能()  加上後就是檢測這個方法的傳回值了           
if(!document.getElementById("xx")){
        return false;
   } 更加針對性           

重點:結構化程式設計 中有個一個原則: 函數應該隻有一個入口和一個出口

如果一個函數有多個出口 隻要這些出口集中出現在函數的開頭部分就可以接受 例子:

function prepareGallery(){
        if(!document.getElementByTagName) return false;
        if(!document.getElementById) return false;
        if(!document.getElementById("imagegallery")) return false;


        接下來就是核心部分
   }           

重點: 如果如果一個變量很長 可以選擇另起一個變量名字來代替它

this代表links[i] 也就是對應的節點

改進後: 這樣就可以将onclick事件綁定到id等于 imagegallery的元素内的各個連結元素上

funciton prepareGallery(){
        if(!document.getElementByTagName) return false;
        if(!document.getElementById) return false;
        if(!document.getElementById("imagegallery")) return false;
        var xx=document.getElementById("imagegallery");
        var yy=xx.getElementByTagName("a");
        for(var i;i<yy.length;i++){
            yy[i].onclick=function(){
                showPic(this);
                return  false;
            }
        }
   }           

重點: 還記得window的onload嗎 這個是網頁加載完畢後觸發的事件

window.onload=firstFunction;
   window.onload=secondFunction;           

這樣第二個會覆寫掉第一個 可以這樣解決

window.onload=function(){
        firstFunction();
        secondFunction();
   }         這是最簡單的解決方案           

還有一個彈性最佳的方案 編寫如下函數即可

function addLoadEvent(func){
        var oldonload=window.onload;
        if(typeof window.onload!='function'){
            window.onload=func;
        } else {
            window.onload=function(){
                oldonload();
                func();
            }
        }
  }           

這樣就相當于建立了個隊列隻需要寫下面代碼就行:

addLoadEvent(firstFunction);
  addLoadEvent(secondFunction);
           

插入一下 剛又思考了下 return false;的問題 又重新回顧一下

<a href="1.html" onclick="popUp('2.html');"> sdf</a>   這個例子中  結果會是原網頁顯示 1.html  并且打開了一個新網頁  2.html
   <a href="1.html" onclick="popUp('2.html');return false;"> sdf</a>              

修改後 這樣 隻會打開一個新網頁 因為return false取消了這個點選的預設情況 意思就是 href無效

再插入一下 一個窗體的打開和關閉:

打開用open

window.onload=function(){
        var oTxt=document.getElementById('txt1');
        var obtn=document.getElementById('btr');
        obtn.onclick=function(){
            va oNewWin=window.open('about:blank','_blank');
            oNewWin.document.write(oTxt.value);
        }
   }           

about:blank表示 打開一個空白視窗

接下來是close 但是再火狐浏覽器下 是無法close一個使用者打開的窗體 隻有一個窗體是用open打開的時候才可以用close方法關閉

window.nevigator.userAgent 擷取目前浏覽器的版本資訊

window.location 擷取目前網頁的位址

尺寸和坐标 : 可視區尺寸就是使用者端能在螢幕上看到網頁部分的尺寸 會随着窗體大小而變化

通過 document.documentElement.clientWidth和

document.documentElement.clientHeight可以擷取目前頁面可視區的寬度和高度

document.body.scrollTop 是滾動距離 是可視區到頁面頂端的距離

window.onresize 是頁面大小改變時觸發的事件

幾個常用的系統對話框

1.alert() 警告框 沒有傳回值
  2.confirm("提問的内容")選擇框 傳回一個 boolean
           

回到之前那個圖檔庫的問題 進行修改

前一件事是必須的 後一件事是錦上添花

function showPic(whichpic){
        if(!document.getElementById("placeholder")) return false;
        var xx=whichpic.getAttribute("href");
        var yy=document.getElementById("placeholder");
        placeholder.setAttribut("src",xx);
        if(document.getElementById("description")){
            var text=whichpic.getAttribute("title");
            var description=document.getElementById("description");
            description.firstChild.nodeValue=text;
        }
  }           

不要做太多假設 之前圖庫我們假設肯定存在placeholder圖檔和description元素 就會出現js錯誤

是以也要修改

function xx(){
    if(!document.getElementById) return false;
    if(!document.getElementByTagName) return false;
    if(!document.getElementById("imagegallery")) return false;
    var gallery=document.getElementById("imagegallery");
    var links=gallery.getElementByTagName("a");
    for(var i=0;i<links.length;i++){
        links[i].onclick=function(){
            return !showPic(this);
        }
    }
  }
           

代碼優化:

function xx(){
    if(!document.getElementById) return false;
    if(!document.getElementByTagName) return false;
    if(!document.getElementById("imagegallery")) return false;
    var gallery=document.getElementById("imagegallery");
    var links=gallery.getElementByTagName("a");
    for(var i=0;i<links.length;i++){
        links[i].onclick=function(){
            return showPic(this)?false:true;
        }
    }
  }           
function showPic(whichpic){
        if(!document.getElementById("placeholder")) return false;
        var xx=whichpic.getAttribute("href");
        var yy=document.getElementById("placeholder");
        if(placeholder.nodeName!="IMG") return false;
        placeholder.setAttribut("src",xx);
        if(document.getElementById("description")){
            var text=whichpic.getAttribute("title")?whichpic.getAttribute("title"):"";
            var description=document.getElementById("description");
            if(description.firstChild.nodeType==3){
            description.firstChild.nodeValue=text;
            }
        }
        return true;
  }
           

總結:

盡量讓js不再依賴假設 引入許多項的測試和檢查 為了平穩退化 事件處理函分離到外部的js檔案 這樣使js不再依賴于html文檔的内容和結構

結構和行為要盡量分離

還有 DOM Core 和HTML-DOM的差別也要注意一下

繼續閱讀