當網頁被加載時,瀏覽器會創建頁面的文檔對象模型(Document Object Model)
HTML DOM 是關於如何獲取、更改、添加或刪除 HTML 元素的標準。
HTML DOM 方法是您能夠(在 HTML 元素上)執行的動作。
HTML DOM 屬性是您能夠設置或改變的 HTML 元素的值。
- 改變HTML樣式
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p id="p1">Hello world!</p>
<p id="p2">Hello world!</p>
<script>
document.getElementById("p2").style.color="blue";
document.getElementById("p2").style.fontFamily="Arial";
document.getElementById("p2").style.fontSize="larger";
</script>
</body>
</html>
- - 輸入關鍵字欄目,實現效果:如果光標不在裏面就顯示請輸入關鍵字,不在裏面就變成空白
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input id="i1" type="text" value="請輸入關鍵字" onfocus="Focus();" onblur="Blur();" />
<script type="text/javascript">
function Focus(){
//console.log('Focus');
//獲取標籤,清空
var tag = document.getElementById('i1');
if(tag.value == "請輸入關鍵字"){
tag.value = "";
}
}
function Blur(){
//console.log('blur');
var tag = document.getElementById('i1');
var val = tag.value;
if(val.trim().length == 0){
tag.value = "請輸入關鍵字";
}
}
</script>
</body>
</html>
document
- document代表整個文檔
HTML DOM 訪問(方法)
-
document.getElementById()
-
可返回對擁有指定 ID 的第一個對象的引用
-
可以用來查找文檔中一個特定的元素
-
如果存在多個指定 ID 的元素則返回第一個,沒有指定ID返回null
<body>
<p id="demo"></p>
<button onClick="myFunction()">點我</button>
</body>
// JavaScript Document
function myFunction(){
document.getElementById("demo").innerHTML="HELLO world";
}
getElementsByTagName()
- 返回帶有指定標籤名的對象的集合:
<div id="aaa"></div>
<p name = "demo"></p>
<div id="bbb"></div>
var div = document.getElementsByTagName('div');
通過getElementsByTagName('div')[0]選出<div id="aaa"></div>
getElementsByName()
- 可返回帶有指定名稱的對象的集合。
- 返回的是元素的數組,而不是一個元素
- 只有部分標籤name可生效(表單,img,iframe)
<body>
<input name="myName" type="text" size="20"/>
<input type="button" onClick="getElements()"value="how many elements named "myInput"" >
</body>
function getElements()
{
var x=document.getElementsByName("myInput");
alert(x.length);
}
getElementsByClassName()
選出來的是所有class爲這個的元素節點的集合
<div class="demo"></div>
<p class = "demo"></p>
<div class="demo">
<span class= "demo"></span>
</div>
var div = document.getElementsByClassName('demo');
querySelector()和querySelectorAll()
querySelector()返回文檔中匹配指定 CSS 選擇器的一個
元素
<div class="demo">
<span class= "demo">a</span>
<i class = "a">123</i>
<div class = "inner">
<strong></strong>
</div>
</div>
var strong= document.querySelector('div.demo div.inner strong');
如果需要返回所有的元素,請使用 querySelectorAll()方法替代。querySelector返回的是單個DOM元素;
querySelectorAll返回的是NodeList.
queryselect()和queryselectAll()缺點它不是實時的,它只是保存了選擇出來的那些元素的副本,
當它們動態改變的時候,用queryselect()和queryselectAll()選出來的還是原來的,不會跟着改變。
- getElementById方法定義在Document.prototype上,即元素節點上不能使用。
- getElementsByName方法定義在HTMLDocument.prototype上,即非html中的document不能使用(xml document,Element)
- getElementsByTagName,getElementsByClassName,querySelector,querySelectorAll方法定義在Document.prototype和Element.prototype上
節點的類型
一般獲取節點類型用node Type
上面的除了children之外的基於元素節點數的遍歷,在ie9以下都不兼容。
形成原型鏈
document--->HTMLDocument.prototype-->Document.prototype-->Node.prototype-->EventTarget.prototype-->Object.prototype-->null
節點的四個屬性
屬性是節點(HTML 元素)的值,您能夠獲取或設置。
nodeName
元素的標籤名,以大寫形式表示,只讀
-
元素節點的 nodeName 與標籤名相同
-
屬性節點的 nodeName 與屬性名相同
-
文本節點的 nodeName 始終是 #text
-
文檔節點的 nodeName 始終是 #document
注意: nodeName 始終包含 HTML 元素的大寫字母標籤名。
nodeValue
規定節點的值
Text節點或Comment節點的文本內容,可讀寫
-
元素節點的 nodeValue 是 undefined 或 null
-
文本節點的 nodeValue 是文本本身
-
屬性節點的 nodeValue 是屬性值
nodeType(重要)
該節點的類型,只讀
attributes
Element節點的屬性集合
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>abraham</title>
</head>
<body>
<div>123
<!-- this is comment -->
<strong></strong>
<span></span>
<em></em>
<i></i>
<b></b>
</div>
<script type="text/javascript">
var div = document.getElementsByTagName("div")[0];
</script>
</body>
</html>
nodeName
只能讀取值,不能寫入值
nodeValue
nodeType
最有用的一個屬性。可以幫助我們分辨這個節點的類型
只讀
把div下面的元素節點全部跳出來,放到一個數組裏面,返回:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>abraham</title>
</head>
<body>
<div>123
<!-- this is comment -->
<strong></strong>
<span></span>
<em></em>
<i></i>
<b></b>
</div>
<script type="text/javascript">
var div = document.getElementsByTagName("div")[0];
function retElementChild(node){
//no children
var arr = [],
child = node.childNodes,
len = child.length;
for(var i = 0; i < len; i ++){
if(child[i].nodeType == 1)
arr.push(child[i])
}
return arr;
}
console.log(retElementChild(div));
</script>
</body>
</html>
attributes節點(元素)的屬性節點
可以更改屬性值,但是不能更改屬性名
元素節點
Element節點的一些屬性
innerHTML節點(屬性)的文本值
- 獲取元素內容的最簡單方法是使用 innerHTML 屬性。
- innerHTML 屬性對於獲取或替換 HTML 元素的內容很有用。
- innerHTML 屬性可用於獲取或改變任意 HTML 元素,包括
<html>
和<body>。
(2)innerText(火狐不兼容)/textContent(老版本IE不好使)
(3)parentNode - 節點(元素)的父節點
(4)childNodes - 節點(元素)的子節點
(6)attributes - 節點(元素)的屬性節點
Element節點的一些方法
(1)element.setAttribute()
(2)element.getAttribute()
Element節點的操作
插入:
parentNode.appendChild(node)插入新的子節點元素
parentNode.insertBefore(a,b)
createElement()
如需向 HTML DOM 添加新元素,您首先必須創建該元素(元素節點),然後把它追加到已有的元素上。
<body>
<div id="div1">
<p id="p1">這是一個段落。</p>
<p id="p2">這是另一個段落。</p>
</div>
<script>
var para=document.createElement("p");
//這段代碼創建了一個新的 <p> 元素
var node=document.createTextNode("這是一個新段落。");
//如需向 <p> 元素添加文本,您首先必須創建文本節點。這段代碼創建文本節點
para.appendChild(node);
//然後您必須向 <p> 元素追加文本節點
var element=document.getElementById("div1");
//最後,您必須向已有元素追加這個新元素。這段代碼查找到一個已有的元素
element.appendChild(para);
//這段代碼向這個已存在的元素追加新元素
</script>
insertBefore()
<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");
var child=document.getElementById("p1");
element.insertBefore(para,child);
</script>
刪除:
parent.removeChild(node)
child.remove()
<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>
替換:
parent.replaceChild(new, origin)
<div id="div1">
<p id="p1">這是一個段落。</p>
<p id="p2">這是另外一個段落。</p>
</div>
<script>
var parent=document.getElementById("div1");
var child=document.getElementById("p1");
var para=document.createElement("p");
var node=document.createTextNode("這是一個新的段落。");
para.appendChild(node);
parent.replaceChild(para,child);
</script>
小練習
1.封裝函數,返回元素e的第n’層父級元素節點
<body>
<div> <strong> <span> <i> </i> </span> </strong> </div>
<body>
function retParent(elem, n){
while(elem && n){
elem = elem.parentElement;
n--;
}
return elem;
}
var i==document.getElementsByTagName("i")[0];
2.在原型鏈上編輯函數,封裝myChildren功能,解決以前部分瀏覽器不兼容的問題
<div>
<strong>
<span>
<i></i>
</span>
<strong>123</strong>
<img src="" alt="">
</strong>
<div></div>
</div>
var div = document.getElementsByTagName('div')[0];
Element.prototype.myChildren = function () {
var child = this.childNodes;
var len = child.length;
var arr = [];
for(var i = 0; i < len; i++){
if(child[i].nodeType === 1){
arr.push(child[i]);
}
}
return arr;
}
console.log(div.myChildren());//Array [ strong, div ]
3.封裝函數,返回元素e的第n個兄弟元素節點;n爲正,返回後面的兄弟元素節點;n爲負,返回前面的兄弟元素節點;n爲0,返回自己。
function retSibling(e, n){
while(e && n){
if(n > 0){
e = e.nextElementSibling;
n--;
}else{
e = e.previousElementSibling;
n++;
}
}
return e;
}
//解決nextElementSibling在IE裏面不兼容的問題:
function retSibling(e, n){
while(e && n){
if(n > 0){
if(e.nextElementSibling){
e = e.nextElementSibling;
}else{
for(e = e.nextSibling; e && e.nodeType != 1; e = e.nextSibling);
}
n--;
}else{
if(e.previousElementSibling){
e = e.previousElementSibling;
}else{
for(e = e.previousSibling; e && e.nodeType != 1; e = e.previousSibling);
}
n++;
}
}
return e;
}
4.封裝一個自己的myHasChildren方法,不可用children屬性
Element.prototype.myHasChildren = function () {
var child = this.childNodes;
var len = child.length;
for(var i = 0; i < len; i++){
if(child[i].nodeType === 1){
return true;
}
}
return false;
}
var div = document.getElementsByTagName('div')[0];
console.log(div.myHasChildren());//true
5.不用children方法遍歷元素直接子節點
<div>
<i></i>
<strong></strong>
<span></span>
<div>
<img src="" alt="">
</div>
</div>
var div = document.getElementsByTagName('div')[0];
function retElementchild(node) {
var temp = {
length : 0,
push : Array.prototype.push,
splice : Array.prototype.splice
},
child = node.childNodes,
len = child.length;
for(var i = 0; i < len; i++){
if(child[i].nodeType ===1){
temp.push(child[i]);
}
}
return temp;
}
console.log(retElementchild(div));
//Object { 0: i, 1: strong, 2: span, 3: div, length: 4, push: push(), splice: splice() }
6.封裝函數insertAfter() 類似於 insertBefore()
<div>
<i></i>
<strong></strong>
<span></span>
<div>
<img src="" alt="">
</div>
</div>
<script type="text/javascript">
var div = document.getElementsByTagName('div')[0];
var span = document.getElementsByTagName('span')[0];
var p = document.createElement('p');
Element.prototype.insertAfter = function(targetNode,OriginNode) {
var afterS=OriginNode.nextElementSibling;
if (afterS==null) {
this.appendChild(targetNode);
}else{
this.insertBefore(targetNode,afterS);
}
}
div.insertAfter(p,span);
結果如下
<div>
<i></i>
<strong></strong>
<span></span>
<p></p>
<div>
<img src="" alt="">
</div>
</div>
7.將目標節點內的節點順序逆序
<div>
<i></i>
<strong></strong>
<span></span>
</div>
var div = document.getElementsByTagName('div')[0];
function reverse(a) {
for (var i =a.children.length-2; i >=0; i--) {
a.appendChild(a.children[i]);
}
return a.children;
}
console.log(reverse(div));//HTMLCollection(3) [ span, strong, i ]
物塊運動
鍵盤控制圖片運動
<body>
<div id="main">
<img src="QQ圖片20200217100543.jpg" >
</div>
</body>
#main {
position: absolute;
top: 0px;
left: 0px;
}
#main img {
display: block;
width: 100px;
height: 100px;
}
// JavaScript Document
sy = 0;
vy = 30;
sx = 0;
vx = 30;
document.onkeydown = function (event) { //對用戶敲擊鍵盤事件進行監聽
code = event.keyCode; //獲取按下的鍵盤按鍵Unicode值:
switch (code) {
case 37:
//往左走
sx -= vx;
main.style.left = sx + 'px';
break;
case 38:
//往上走
sy -= vy;
main.style.top = sy + 'px';
break;
case 39:
//往右走
sx += vx;
main.style.left = sx + 'px';
break;
case 40:
//往下走
sy += vy;
main.style.top = sy + 'px';
break;
}
}
使用事件
HTML DOM 允許您在事件發生時執行代碼。
當 HTML 元素"有事情發生"時,瀏覽器就會生成事件:
點擊按鈕改變背景顏色
第一種方法
<input type="button"
onclick="document.body.style.backgroundColor='lavender';"
value="修改背景顏色">
第二種方法
<input type="button" onclick="ChangeBackground()" value="修改背景顏色" />
<script>
function ChangeBackground()
{
document.body.style.backgroundColor="lavender";
}
</script>
點擊文本改變文本內容
<script>
function changetext(id){
id.innerHTML="Ooops!";
}
</script>
<body>
<h1 onclick="changetext(this)">點擊文本!</h1>
</body>
點擊
事件屬性
<p id="demo"></p>
<button onclick="displayDate()">點我</button>
<script>
function displayDate()
{
document.getElementById("demo").innerHTML=Date();
}
</script>
分配事件
名爲 displayDate 的函數被分配給了 id=myButn" 的 HTML 元素。
當按鈕被點擊時,將執行函數。
<button id="myBtn">點我</button>
<p id="demo"></p>
<script>
document.getElementById("myBtn").onclick=function(){displayDate()};
function displayDate()
{
document.getElementById("demo").innerHTML=Date();
}
</script>
onload 和 onunload 事件
- 當用戶進入或離開頁面時,會觸發 onload 和 onunload 事件。
- onload 事件可用於檢查訪客的瀏覽器類型和版本,以便基於這些信息來加載不同版本的網頁。
- onload 和 onunload 事件可用於處理 cookies。
<body onload="checkCookies()">
<script>
function checkCookies()
{
if (navigator.cookieEnabled==true)
{
alert("Cookie 可用")
}
else
{
alert("Cookie 不可用")
}
}
</script>
頁面載入時,彈出瀏覽器 Cookie 可用狀態。
onchange 事件
onchange 事件常用於輸入字段的驗證。
<script>
function myFunction(){
var x=document.getElementById("fname");
x.value=x.value.toUpperCase();
}
</script>
輸入你的名字: <input type="text" id="fname" onchange="myFunction()">
當你離開輸入框後,函數將被觸發,將小寫字母轉爲大寫字母。
onmouseover 和 onmouseout 事件
可用於在鼠標指針移動到或離開元素時觸發函數。
<div onmouseover="mOver(this)" onmouseout="mOut(this)" style="background-color:#D94A38;width:120pxheight:20px;padding:40px;">Mouse Over Me</div>
<script>
function mOver(obj)
{
obj.innerHTML="Thank You"
}
function mOut(obj)
{
obj.innerHTML="Mouse Over Me"
}
</script>
onmousedown、onmouseup 以及 onclick 事件是鼠標點擊的全部過程。
- 首先當某個鼠標按鈕被點擊時,觸發 onmousedown 事件,
- 然後,當鼠標按鈕被鬆開時,會觸發 onmouseup 事件,
- 最後,當鼠標點擊完成時,觸發 onclick 事件。
<div onmousedown="mDown(this)" onmouseup="mUp(this)" style="background-color:#D94A38;width:90px;height:20px;padding:40px;">Click Me</div>
<script>
function mDown(obj)
{
obj.style.backgroundColor="#1ec5e5";
obj.innerHTML="Release Me"
}
function mUp(obj)
{
obj.style.backgroundColor="#D94A38";
obj.innerHTML="Thank You"
}
</script>
點擊前
點擊時
點擊後
HTML DOM 導航
使用節點關係在節點樹中導航
getElementsByTagName() 方法返回節點列表。節點列表是一個節點數組
<p>Hello World!</p>
<p>DOM 是非常有用的!</p>
<script>
x=document.getElementsByTagName("p");
document.write("第二個段落的 innerHTML 內容爲: " + x[1].innerHTML);
</script>
節點列表長度
length 屬性定義節點列表中節點的數量。
可以使用 length 屬性來循環節點列表:
<p>Hello World!</p>
<p>DOM 是非常有用的!</p>
<p>這個實例演示了 <b>length</b> 屬性。</p>
<script>
x=document.getElementsByTagName("p");
for (i=0;i<x.length;i++)
{
document.write(x[i].innerHTML);
document.write("<br>");
}
</script>
-
獲取所有 < p> 元素節點
-
輸出每個 < p> 元素的文本節點的值
導航節點關係
三個節點屬性:parentNode、firstChild 以及 lastChild ,在文檔結構中進行導航
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>Hello World!</p>
<div>
<p>DOM 是非常有用的!</p>
<p>這個實例演示了節點的關係。</p>
</div>
</body>
</html>
-
首個 < p> 元素是 < body> 元素的首個子元素(firstChild)
-
< div> 元素是 < body> 元素的最後一個子元素(lastChild)
-
< body> 元素是首個 < p> 元素和 < div> 元素的父節點(parentNode)
firstChild 屬性可用於訪問元素的文本:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p id="intro">Hello World!</p>
<script>
x=document.getElementById("intro");
document.write(x.firstChild.nodeValue);
</script>
</body>
</html>
這裏有兩個特殊的屬性,可以訪問全部文檔:
- document.documentElement - 全部文檔
- document.body - 文檔的主體
alert(document.body.innerHTML);
childNodes 和 nodeValue
來獲取元素的內容
<p id="intro">Hello World!</p>
txt=document.getElementById("intro").childNodes[0].nodeValue;
document.write(txt);
getElementById 是一個方法,而 childNodes 和 nodeValue 是屬性