1,DOM操作
1.1 概念
所謂DOM,全稱Document Object Model 文檔對象模型,DOM是W3C(World Wide Web Consortuum )標准,同時也定義了訪問諸如XML和HTML文檔的標准。DOM是一個使程序和腳本有能力動態地訪問和更新文檔的內容,結構以及樣式的平台和語言中立的接口。
在文檔中一切皆對象,比如 html,body,div,p等等都看做對象,那么我們如何來點擊某個盒子讓他變色呢?
DOM 為文檔提供了結構化表示,並定義了如何通過腳本來訪問文檔結構。目的其實就是為了能讓 js 操作 html 元素而制定的一個規范。
1.2 解析過程
HTML 加載完畢,渲染引擎會在內存中把HTML文檔,生成一個DOM樹,getElementByid 是獲取內中DOM上的元素節點。然后操作的時候修改的是該元素的屬性。
1.3 DOM(樹)一切皆是節點
HTML 標簽通過瀏覽器的解析后才會形成DOM樹,此后HTML中的每個標簽元素,屬性,文本都能看做是一個DOM的節點,JavaScript都能通過DOM的提供的編程接口操作到每個節點,去了解瀏覽器的渲染機制能夠幫助我們了解DOM。
上圖可知,在HTML當中,一切都是節點,並且文本節點和屬性節點屬於元素節點:
- 元素節點:HTML標簽
- 文本節點:標簽中的文字(比如標簽之間的空格,換行)
- 屬性節點:標簽的屬性
整個html 文檔就是一個文檔節點,所有的節點都是Object。要注意:文本節點和屬性節點就像這棵DOM樹的果子,而元素節點就是樹枝,所以,在操作時,一定要記順枝摘果:得先取到元素節點,然后再操作子節點!!!
1.4 DOM可以做什么?
- 找對象(元素節點)
- 設置元素的屬性值
- 設置元素的樣式
- 動態創建和刪除元素
- 事件的觸發響應:事件源,事件,事件的驅動程序
1.5 清楚DOM的結構
- 獲取文檔對象:document
- 獲取html:document.documentElement
- 獲取body:document.body
1.6 常用DOM對象方法
下面列出常用的DOM對象方法:
操作代碼如下:
<head> <meta charset="UTF-8"> <title></title> <style type="text/css"> .active{ width: 200px; height: 200px; background-color:red; color: white; line-height:200px; text-align:center; font-size:30px; } </style> </head> <body> <div id="box"> <p id="active">this is p label</p> <p>this also is p label</p> </div> <!-- 動態的操作節點 1,創建節點 createElement() 2,插入節點 appendChild() insertBefore(newNode, node) 3,刪除節點 removeChild() 4,替換節點 replaceChild(newNode, node) 5,創建文本節點 createTextNode()--> <script type="text/javascript"> var oDiv = document.getElementById('box'); // 創建節點 var newNode = document.createElement('p'); // 插入節點 oDiv.appendChild(newNode); // 設置屬性 newNode.setAttribute('class', 'active'); // 創建文本 節點 var textNode = document.createTextNode('this is p label too'); oDiv.appendChild(textNode); var newNode1 = document.createElement('p'); var newNode2 = document.createElement('p'); oDiv.appendChild(newNode1); oDiv.appendChild(newNode2); // 創建innerHTML newNode1.innerHTML = '<a href="#">123.qq.com</a>'; newNode2.innerText = '<a href="#">123.qq.com</a>'; // 釋放節點 // newNode2 = null; // 刪除節點 // oDiv.remove(newNode2) </script>
效果如下:
在頁面查看的html代碼如下:
1.7 獲取其他DOM(事件源)的四種方法
其實可以通過使用getElement系列方法,取到元素節點。
//方式一:通過id獲取單個標簽 var oDiv1 = document.getElementById("box1"); //方式二:通過 標簽名 獲得 標簽數組,所以有s var oDiv2 = document.getElementsByTagName("div")[0]; //方式三:通過 類名 獲得 標簽數組,所以有s var oDiv3 = document.getElementsByClassName("box")[0]; //方式四:通過 name屬性 獲得id號,返回元素對象數組 var oDiv3 = document.getElementsByName("box")[0];
1.8 獲取/設置元素的屬性值
- 1,element.getAttribute(attrubuteName) // 括號傳入屬性名,返回對應屬性的屬性值
- 2,element.setAttribute(attributeName, attributeValue) // 傳入屬性名及設置的值
1.9 創建節點 Node
- 1,document.createElement('h3') // 創建一個html元素
- 2,document.createTextNode(string) // 創建一個文本節點
- 1,document.createAttribute('class') // 創建一個屬性節點
1.10 增添節點
- 1,element.appendChild(Node) // 往element內部最后面添加一個節點,參數是節點類型
- 2,element.insertBefore(newNode, existingNode) // 在element內部中在existingNode前面插入 newNode
1.11 刪除節點
- 1,element.removeChild(Node) // 刪除當前節點下指定的子節點,刪除成功返回該刪除的節點,否則返回 null
2,事件
JS 是事件驅動為核心的一門語言。
2.1,事件三要素
事件源,事件,事件驅動程序
比如,我用手去按開關,燈亮了。這件事情里,事件源是:手。事件是:按開關。事件驅動程序是:燈的開和關。
再比如,網頁上彈出一個廣告,我點擊右上角的 x,廣告就關閉了。這件事情里,事件源是:x,事件是 onclick。事件驅動程序是:廣告關閉了。
於是我們可以總結出:誰引發的后續事件,誰就是事件源。
- 事件源:引發后續事件的html標簽
- 事件:js已經定義好了(如下圖)
- 事件驅動程序:對樣式和HTML的操作,也就是DOM。
代碼書寫步驟如下:
(1)獲取事件源:document.getElementById(“box”); //類似與ios語言的UIButton *adBtn = [UIButton buttonWithType:UIButtonTypeCustom]; (2)綁定事件: 事件源box.事件onclick = function(){ 事件驅動程序 }; (3)書寫事件驅動程序:關於DOM的操作
常用事件如下:
2.2,綁定事件的方法
直接綁定匿名函數
var oDiv = document.getElementById("box"); //綁定事件的第一種方式 oDiv.onclick = function () { alert("我是彈出的內容"); };
先單獨定義函數,再綁定
var oDiv = document.getElementById("box"); //綁定事件的第二種方式 oDiv.onclick = fn; //注意,這里是fn,不是fn()。fn()指的是返回值。 //單獨定義函數 function fn() { alert("我是彈出的內容"); };
注意上方代碼的注釋。綁定的時候,是寫 fn,而不是 fn()。fn代表的是整個函數,而fn() 代表的是返回值。
行內綁定
<!--行內綁定--> <div id="box" onclick="fn()"></div> <script type="text/javascript"> function fn() { alert("我是彈出的內容"); } </script>
注意第一行代碼,綁定時,是寫的“fn()”,不是寫的“fn”。因為綁定的這段代碼不是寫在js代碼里的,而是被識別成了字符串。
2.3 JavaScript入口函數 window.onload()
此函數調用,是當頁面加載完畢(文檔和圖片)的時候,觸發 onload() 函數,文檔先加載,圖片資源后加載。
<script type="text/javascript"> window.onload = function () { console.log("james"); //等頁面加載完畢時,打印字符串 } </script>
有一點我們要知道:js的加載是和html 同步加載的。因此,如果使用元素在定義元素之前,容易報錯。這個時候onload事件就能派上用場了,我們可以把使用元素的代碼放在 onload 里,就能保證這段代碼是最后執行。
window.onload() 方法存在的問題
- 圖片加載完成才調用onload方法,大家想個問題,如果現在用戶訪問JD商城頁面,如果JD商城中的腳本文件在 window.onload() 方法調用,如果此時用戶網速卡了,然后圖片資源加載失敗了,此時用戶是做不了任何操作的,所以 window.onload() 方法有很大的問題。
- window.onload() 方法如果腳本中書寫兩個這樣的方法,那么會有事件覆蓋現象。
2.4 樣式屬性操作
所謂樣式書寫,就是對之前所講解的 style 標簽中的屬性進行操作,並且通過 js 控制盒模型的屬性(width,height等),控制盒子的顯示隱藏(display: none|block),控制盒子的顏色切換(background:red|green)等等。
首先大家明確一點,你要操作文檔對象了,要遵循事件三步走:
- 獲取事件源
- 事件
- 事件驅動程序
<div id='box'></div> <script> window.onload = function(){ //1.獲取事件源(事件對象,在文檔中一切的標簽都是對象) var oDiv = docuement.getElementById('box'); //2.事件 oDiv.onclick = function(){ //3.事件驅動程序 ps:記得 所有的style中使用的像margin-left //在js操作時都是用marginLeft屬性進行賦值 oDiv.style.backgroundColor = 'yellow'; } }; </script>
2.5 值的操作
所謂值的操作,就是對前閉合標簽和后閉合標簽中間的文本內容的設置和獲取。
- 雙閉合標簽:innerText或者innerHTML
- 單閉合標簽:除了img標簽,就剩 input了,使用value進行賦值
<div id='box'></div> <input type='text' value = 'james' id='user'> <script> window.onload = function(){ //1.獲取事件源(事件對象,在文檔中一切的標簽都是對象) var oDiv = docuement.getElementById('box'); var oInput = docuement.getElementById('user'); //2.事件 oDiv.onclick = function(){ //3.事件驅動程序 oDiv.innerText = 'james';//僅僅設置文本內容 oDiv.innerHTML = '<h1>james</h1>';//將標簽和文本內容一起解析 }; //2.事件 oInput.onclick = function(){ //3.事件驅動程序 只有有value屬性的 才能使用value賦值和設置值 oInput.value = 'the king'; } }; </script>
2.6 標簽屬性操作
所謂標簽屬性,就是對標簽中(字面上看到的)屬性的操作。比如像每個標簽中 id,class,title,img 標簽的src屬性和 alt屬性,a標簽的href屬性,input標簽中的name,type 屬性等等。
<script> //window.onload頁面加載完畢以后再執行此代碼 window.onload = function () { //需求:鼠標放到img上,更換為另一張圖片,也就是修改路徑(src的值)。 //步驟: //1.獲取事件源 //2.綁定事件 //3.書寫事件驅動程序 //1.獲取事件源 var oImg = document.getElementById("box"); //2.綁定事件(懸停事件:鼠標進入到事件源中立即出發事件) oImg.onmouseover = function () { //3.書寫事件驅動程序(修改src) img.src = "image/jd2.png"; // this.src = "image/jd2.png"; } //2.綁定事件(懸停事件:鼠標進入到事件源中立即出發事件) oImg.onmouseout = function () { //3.書寫事件驅動程序(修改src) img.src = "image/jd1.png"; } } </script>
3,節點操作
都是函數(方法)。JavaScript原生方法對DOM節點的操作包括:訪問(查找),創建,添加,刪除,替換,插入,復制,移動等。
總體代碼總結如下:
//查找節點 document.getElementById("id");// 通過id查找,返回唯一的節點 document.getElementsByClassName("class");// 通過class查找,返回值為nodeList類型 document.getElementsByTagName("div");// 通過標簽名查找,返回值為nodeList類型 //創建節點 document.createDocumentFragment();//創建內存文檔碎片 document.createElement();//創建元素 document.createTextNode();//創建文本節點 //添加節點 var ele = document.getElementById("my_div"); var oldEle = document.createElement("p"); var newEle=document.createElement("div"); ele.appendChild(oldEle); //刪除節點 ele.removeChild(oldEle); //替換節點 ele.replaceChild(newEle,oldEle); //插入節點 ele.insertBefore(oldEle,newEle);//在newEle之前插入 oldEle節點 //復制節點 var cEle = oldEle.cloneNode(true);//深度復制,復制節點下面所有的子節點 cEle = oldEle.cloneNode(false);//只復制當前節點,不復制子節點 //移動節點 var cloneEle = oldEle.cloneNode(true);//被移動的節點 document.removeChild(oldEle);//刪除原節點 document.insertBefore(cloneEle,newEle);//插入到目標節點之前
下面我們一一學習。
3.1 創建節點
格式如下:
新的標簽(元素節點) = document.createElement("標簽名");
比如,如果我們想創建一個 li 標簽,或者是創建一個不存在的 adbc 標簽,可以這樣做:
<script type="text/javascript"> var a1 = document.createElement("li"); //創建一個li標簽 var a2 = document.createElement("adbc"); //創建一個不存在的標簽 console.log(a1); console.log(a2); console.log(typeof a1); console.log(typeof a2); </script>
結果如下
3.2 插入節點
插入節點有兩種方式,他們的含義是不同的。
方式1:
父節點.appendChild(新的子節點);
解釋:父節點的最后插入一個新的子節點(屬性節點,文本節點,元素節點)。
方式2:
父節點.insertBefore(新的子節點,作為參考的子節點);
解釋:
- 在參考節點前插入一個新的節點。
- 如果參考節點為 null,那么他將在父節點最后插入一個子節點。
3.3 刪除節點
格式如下:
父節點.removeChild(子節點);
解釋:用父節點刪除子節點。必須要指定是刪除那個子節點。
如果我想刪除自己這個節點,那么可以這樣做:
node1.parentNode.removeChild(node1);
4,DOM操作的常用屬性
4.1,獲取當前元素的父節點
element.parentNode //返回當前元素的父節點對象
4.2,獲取當前元素的子節點
//返回當前元素所有子元素節點對象,只返回HTML節點 element.chlidren //返回當前元素多有子節點,包括文本,HTML,屬性節點。(回車也會當做一個節點) element.chilidNodes //返回當前元素的第一個子節點對象 element.firstChild //返回當前元素的最后一個子節點對象 element.lastChild
4.3,獲取當前元素的同級元素
//返回當前元素的下一個同級元素 沒有就返回null element.nextSibling //返回當前元素上一個同級元素 沒有就返回null element.previousSibling
4.4,獲取當前元素的文本
//返回元素的所有文本,包括html代碼 element.innerHTML //返回當前元素的自身及子代所有文本值,只是文本內容,不包括html代碼 element.innerText
4.5,獲取當前元素的節點類型
//返回節點的類型,數字形式(1-12)常見幾個1:元素節點,2:屬性節點,3:文本節點。 node.nodeType
4.6,設置樣式
//設置元素的樣式時使用style,這里以設置文字顏色為例 element.style.color=“#eea”;
5,DOM的節點對象屬性在各瀏覽器兼容性處理
5.1 innerHTML屬性和innerText屬性的區別
document 對象中有 innerHTML和 innerText 兩個屬性,這兩個屬性都是獲取 document 對象的文本內容的,這兩個屬性的區別下面學習一下:
innerHTML 返回從 body元素開始所有的帶標簽的文本內容,並按照在HTML文檔中的原格式顯示
innerText 返回從 body 元素開始所有的文本內容,但是它去除HTML標簽
同時,innerHTML 是所有瀏覽器都支持的,innerText 是IE瀏覽器和chrome 瀏覽器支持的,Firefox瀏覽器不支持。其實,innerHTML 是W3C 組織規定的屬性;而innerText 屬性是IE瀏覽器自己的屬性,不過后來的瀏覽器部分實現這個屬性罷了。
下面看個示例:
<body> <div id = "box1"> hello div 1 </div> <div id = "box2"> <p>hello p 1</p> <p>hello p 2</p> </div> <script type="text/javascript"> var oNode = document.getElementById('box1'); console.log(oNode.innerHTML); console.log(oNode.innerText); </script>
控制台打印如下:
通過示例,我們很清楚的發現,innerHTML是帶有標簽的文本內容,並且按照原格式顯示(包括空格);而innerText只是內容,去除了HTML標簽。
6,DOM操作的代碼過程
6.1 先找樹枝——獲取元素節點
首先可以通過 getElement 系列的方法,取到元素節點。
下面展示一個代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> .btn{ width: 200px; height: 200px; background-color:red; color: white; line-height:200px; text-align:center; font-size:30px; } </style> </head> <body> <div class="btn" id="box" onclick="add()"> hello dom </div> <script type="text/javascript"> window.onload = function(){ var oDiv = document.getElementById('box'); console.log(oDiv); <!-- 這個注釋的代碼 只能一次性的轉換--> <!-- oDiv.onclick = function add(){--> <!-- // this指向了當前元素的節點對象--> <!-- console.log(this);--> <!-- this.style.backgroundColor = 'green';--> <!-- }--> var flag = true; oDiv.onclick = function add(){ if (flag){ this.style.backgroundColor = 'green'; flag = false; }else{ this.style.backgroundColor = 'red'; flag = true; } } } </script> </body> </html>
原圖和效果圖如下:
下面我們通過 name屬性 ,標簽屬性和 class名,直接看一下怎么使用:
<div class="btn" id="box" onclick="add()"> hello dom </div> <script type="text/javascript"> var idName = document.getElementById("box"); var className = document.getElementsByClassName("btn"); var tagName = document.getElementsByTagName("div"); var name = document.getElementsByName("btn"); console.log(idName) console.log(className) console.log(tagName); console.log(name); </script>
結果如下:
注意:獲取元素節點時,一定要注意:獲取節點的語句,必須在DOM渲染完成后執行。可以有兩種方式實現:1將JS代碼寫在BODY之后,2將代碼寫到 window.onload函數之中;后面三個 getElements,取到的是數組格式,不能直接添加各種屬性,而應該去除數組的每一個單獨操作:
getElementsByName("name1")[0].onclick = function;
6.2 再找樹枝摘果子——查看設置屬性節點
首先我們注意:查看和設置屬性節點,必須先取到元素節點,才能使用;
下面看查看和設置屬性節點函數:
1、查看屬性節點:getAttribute("屬性名");
2、設置屬性節點:setAttribute("屬性名","新屬性值");
下面代碼展示了查看和設置屬性節點:
<head> <meta charset="UTF-8"> <title></title> <style type="text/css"> #box{ width: 200px; height: 200px; background-color:red; color: white; line-height:200px; text-align:center; font-size:30px; } </style> </head> <body> <p title="p的title">this is p</p> <ul id="classList"> <li class="'item">JavaScript</li> <li class="'item">CSS</li> </ul> <script type="text/javascript"> var oP = document.getElementsByTagName('p')[0]; console.log(document.getElementsByTagName('p')); console.log(oP); // 設置屬性值 有一個必需的參數,這個節點對象的名字 var title = oP.getAttribute('title'); console.log(title); var className = oP.getAttribute('class'); console.log(className); // 設置屬性值 oP.setAttribute("id", 'box'); </script> </body>
我們查看網頁(包括控制台打印的結果):
查看網頁源碼,我們發現id被賦值了:
注意:這里 setAtribute()函數在IE瀏覽器中可能會存在兼容性問題。比如在IE中不支持這個函數設置 style onclick。等樣式屬性和事件屬性。
我們推薦使用符號法替代上述函數:
eg:dom1.style.color="" dom1.onclick="" dom1.src=""
總結:js修改DOM節點的樣式
1,使用setAttribute() 設置 class和style 屬性,但是存在兼容性問題,不提倡;
div.setAttribute("class","cls1");
2,使用 .className直接設置class類,注意是className而不是 .class:
div.className = "cls1";
3,使用 .style 設置單個屬性,注意屬性名要用駝峰命名法:
div.style.backgroundColor = "red";
4,使用 .style 或者 .style.cssText 設置多個樣式屬性:
div.style = "background-color:red;color:yellow;" div.style = "background - color:red;color:yellow" √
6.3 查看設置文本節點
- .innerText:取到或設置節點里面的文字內容;
- .innerHTML:取到或設置節點里面的HTML代碼;
- .tagName:取到當前結點的標簽名。標簽名全部大寫
上面已經學習過,就不多學習。
7,DOM事件練習
在HTML中允許JavaScript對HTML事件作出反應。比如當用戶點擊一個HTML元素時,如需要在用戶點擊某個元素執行代碼,請把JavaScript代碼添加到HTML事件屬性中。
HTML事件的例子練習:
- 當用戶點擊鼠標時
- 當網頁已加載時
- 當圖片已加載時
- 當鼠標移動到元素上時
- 當輸入字段被改變時
- 當 HTML 表單被提交時
- 當用戶觸發按鍵時
也就是上面學習的事件常用函數的使用,下面一一練習:
7.1,當用戶點擊時,會改變<h1>元素的內容
代碼如下:
<h1 onclick="this.innerHTML='hello!'">請點擊這段文本!</h1>
原圖及其效果:
7.2,下面會從事件處理程序中調用函數
代碼如下(效果和上面相同,這里不展示)
<h1 onclick="changetext(this)">請點擊這段文本!</h1> <script type="text/javascript"> function changetext(id){ id.innerHTML = 'hello!'; } </script>
7.3,向button元素分配一個onclick()事件(HTML事件屬性)
如需向HTML元素分配事件,你可以使用事件屬性。
<p >點擊按鈕來執行<b>displayDate()</b>函數。</p> <button onclick="displayDate()">試一試</button> <p id="demo"></p> <script type="text/javascript"> function displayDate(){ document.getElementById('demo').innerHTML = Date(); } </script>
我們點擊按鈕時,會執行名為 displayDate()的函數,效果如下:
7.4,為button元素分配onclick()事件(使用HTML DOM分配事件)
HTML DOM 允許你使用JavaScript向HTML元素分配事件,比如為button元素分配 onclick事件:
<p >點擊按鈕來執行<b>displayDate()</b>函數。</p> <button id="myBtn">試一試</button> <p id="demo"></p> <script type="text/javascript"> document.getElementById('myBtn').onclick=function(){ displayDate() }; function displayDate(){ document.getElementById('demo').innerHTML=Date(); } </script>
效果和上面相同,只不過名為 displayDate 的函數被分配給了 id='myBtn'的HTML元素,當按鈕被點擊時,將執行函數。
7.5,onload() 和 onunload() 事件
當用戶進入或離開頁面時,會觸發 onload 和 onunload 事件
onload事件用於檢查訪客的瀏覽器類型和版本,以便基於這些信息來加載不同版本的網頁。等待文檔元素加載完成才會調用 onload() 事件。
onload和 onunload事件可用於處理 cookies。
代碼如下:
<body onload="checkCookies()"> <p>彈出的提示框會告訴你瀏覽器是否已啟用 cookie</p> <script type="text/javascript"> function checkCookies(){ if (navigator.cookieEnbaled==true) { alert('Cookies are enabled') }else{ alert('Cookies are not enabled') } } </script>
效果如下:
7.6,onchange事件
onchange事件常用於輸入字段的驗證。
下面的例子展示了如何使用 onchange。當用戶改變輸入字段的內容時,將調用 upperCase() 函數。
代碼如下:
請輸入你的英文名: <input type="text" id="fname" onchange="myFunction()"> <p>當你離開輸入框時,被觸發的函數會把你輸入的文本轉換為大寫字母。</p> <script type="text/javascript"> function myFunction(){ var x=document.getElementById('fname'); x.value = x.value.toUpperCase(); } </script>
效果如下:
7.7,onmouseover和onmouseout事件
onmouseover 和 onmouseout 事件可用於在鼠標指針移動到或離開元素時觸發函數。下面一個簡單的 onmouseover-onmouseout 例子:
<style type="text/css"> .active{ width: 200px; height: 200px; background-color:red; color: white; line-height:200px; text-align:center; font-size:30px; } </style> </head> <body> <div class="active" onmouseover = 'mOver(this)' onmouseout='mOut(this)'> Mouse Over Me </div> <script type="text/javascript"> function mOver(obj){ obj.innerHTML = 'thank you'; } function mOut(obj){ obj.innerHTML = 'please move mouse cursor'; } </script>
效果如下:
7.8,onmousedown,onmouseup以及 onclick 事件
onmousedown、onmouseup 以及 onclick 事件是鼠標點擊的全部過程。首先當某個鼠標按鈕被點擊時,觸發 onmousedown 事件,然后,當鼠標按鈕被松開時,會觸發 onmouseup 事件,最后,當鼠標點擊完成時,觸發 onclick 事件。
代碼如下:
<style type="text/css"> .active{ width: 200px; height: 200px; background-color:red; color: white; line-height:200px; text-align:center; font-size:30px; } </style> </head> <body> <div class="active" onmouseover = 'mDown(this)' onmouseout='mUp(this)'> Mouse Over Me </div> <script type="text/javascript"> function mDown(obj){ obj.style.backgroundColor = 'green'; obj.innerHTML = 'level to mouse'; } function mUp(obj){ obj.style.backgroundColor = 'blue'; obj.innerHTML = 'thank you '; } </script>
效果如下:
參考文獻:https://www.cnblogs.com/Ry-yuan/p/6918155.html