去年寒假在家看完了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("*");
-
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的差別也要注意一下