DOM:文檔對象模型。DOM 爲文檔提供告終構化表示,並定義瞭如何經過腳原本訪問文檔結構。javascript
目的其實就是爲了能讓js操做html元素而制定的一個規範。css
DOM就是由節點組成的。html
HTML加載完畢,渲染引擎會在內存中把HTML文檔,生成一個DOM樹,getElementById是獲取內中DOM上的元素節點。而後操做的時候修改的是該元素的屬性。java
元素節點:HMTL標籤。node
文本節點:標籤中的文字(好比標籤之間的空格、換行)數組
屬性節點::標籤的屬性。瀏覽器
整個html文檔就是一個文檔節點。全部的節點都是Object。數據結構
找對象(元素節點)app
設置元素的屬性值框架
設置元素的樣式
動態建立和刪除元素
事件的觸發響應:事件源、事件、事件的驅動程序
DOM的數據結構以下:
上圖可知,在HTML當中,一切都是節點:(很是重要)
文檔節點(document對象):表明整個文檔
元素節點(element 對象):表明一個元素(標籤)
文本節點(text對象):表明元素(標籤)中的文本
屬性節點(attribute對象):表明一個屬性,元素(標籤)纔有屬性
註釋是註釋節點(comment對象)
JavaScript 能夠經過DOM建立動態的 HTML:
JavaScript 可以改變頁面中的全部 HTML 元素
JavaScript 可以改變頁面中的全部 HTML 屬性
JavaScript 可以改變頁面中的全部 CSS 樣式
JavaScript 可以對頁面中的全部事件作出反應(鼠標點擊事件,鼠標移動事件等)整個html文檔就是一個文檔節點。全部的節點都是Object。
找對象(元素節點)
設置元素的屬性值
設置元素的樣式
動態建立和刪除元素
事件的觸發響應:事件源、事件、事件的驅動程序
DOM節點的獲取方式其實就是獲取事件源的方式。
操做元素節點,必須首先找到該節點。有三種方式能夠獲取DOM節點:
var div1 = document.getElementById("box"); //方式一:經過id獲取單個標籤
var arr1 = document.getElementsByTagName("div"); //方式二:經過 標籤名 得到 標籤數組,因此有s
var arr2 = document.getElementsByClassName("box"); //方式三:經過 類名 得到 標籤數組,因此有s
既然方式2、方式三獲取的是標籤數組,那麼習慣性是先遍歷以後再使用。
特殊狀況:數組中的值只有1個。即使如此,這一個值也是包在數組裏的。這個值的獲取方式以下:
document.getElementsByTagName("div")[0]; //取數組中的第一個元素
document.getElementsByClassName("box")[0]; //取數組中的第一個元素
節點的訪問關係,是以屬性的方式存在的。
JS中的父子兄訪問關係:
這裏咱們要重點知道parentNode和children這兩個屬性的用法比較經常使用。下面分別介紹。
下面的都以這個html爲例子進行操做:
<div class="father">
<span class="s1"></span>
<p id="p1"><span></span></p>
<span class="s2"></span>
</div>
<div class="f">
<span class="s3"></span>
</div>
調用者就是節點。一個節點只有一個父節點,調用方式就是
節點.parentNode
//獲取父親節點的方法具體例子
//獲取p1節點
var p1 = document.getElementById('p1');
// 獲取父親節點
var fa = p1.parentNode;
console.log(fa);
(1)nextSibling:
指的是下一個節點(包括標籤、空文檔和換行節點)
火狐、谷歌、IE9+版本:都指的是下一個節點(包括標籤、空文檔和換行節點)。
IE678版本:指下一個元素節點(標籤)。
本文用的是谷歌瀏覽器,全部這個方式只能獲取到空文檔代碼見(2)後的例子及截圖結果。
(2)nextElementSibling:
火狐、谷歌、IE9+版本:都指的是下一個元素節點(標籤)。
js代碼以下:
// 獲取下一個節點
// 法一:
var pnext1 = p1.nextSibling; //var pnext1 = p1.nextSibling.nextSibling;
console.log(pnext1)
// 法二
var pnext2 = p1.nextElementSibling;
console.log(pnext2);
效果圖爲:
總結:爲了獲取下一個元素節點,咱們能夠這樣作:在IE678中用nextSibling,在火狐谷歌IE9+之後用nextElementSibling。因而,綜合這兩個屬性,能夠這樣寫:
下一個兄弟節點 = 節點.nextElementSibling || 節點.nextSibling
// 綜合方法三:
var pnext = p1.nextElementSibling || p1.nextSibling ;
console.log(pnext)
previous的中文是: 前一個
(1)previousSibling:
火狐、谷歌、IE9+版本:都指的是前一個節點(包括標籤、空文檔和換行節點)。
IE678版本:指前一個元素節點(標籤)。
本文用的是谷歌瀏覽器,全部這個方式只能獲取到空文檔代碼見(2)後的例子及截圖結果。
(2)previousElementSibling:
火狐、谷歌、IE9+版本:都指的是前一個元素節點(標籤)。
// 獲取上一個節點
// 法一:
var pre1 = p1.previousSibling; //var pre1 = p1.previousSibling.previousSibling;
console.log(pre1)
// 法二
var pre2 = p1.previousElementSibling;
console.log(pre2);
總結:爲了獲取前一個元素節點,咱們能夠這樣作:在IE678中用previousSibling,在火狐谷歌IE9+之後用previousElementSibling,因而,綜合這兩個屬性,能夠這樣寫:
前一個兄弟節點 = 節點.previousElementSibling || 節點.previousSibling
// 綜合方法三:
var pre = p1.previousElementSibling || p1.previousSibling;
console.log(pre)
補充:得到任意一個兄弟節點:
節點本身.parentNode.children[index]; //隨意獲得兄弟節點
節點本身.parentNode.children; //獲取全部的兄弟節點(僞數組,包含本身在內)
和2中的同樣3中的(1)的方法也是存在不兼容問題,全部均可以2的解放方法同樣,就不一一舉例。
(1)firstChild:
火狐、谷歌、IE9+版本:都指的是第一個子節點(包括標籤、空文檔和換行節點)。
IE678版本:指第一個子元素節點(標籤)。
(2)firstElementChild:
火狐、谷歌、IE9+版本:都指的是第一個子元素節點(標籤)。
總結:爲了獲取第一個子元素節點,咱們能夠這樣作:在IE678中用firstChild,在火狐谷歌IE9+之後用firstElementChild,因而,綜合這兩個屬性,能夠這樣寫:
第一個子元素節點 = 節點.firstElementChild || 節點.firstChild
(1)lastChild:
火狐、谷歌、IE9+版本:都指的是最後一個子節點(包括標籤、空文檔和換行節點)。
IE678版本:指最後一個子元素節點(標籤)。
(2)lastElementChild:
火狐、谷歌、IE9+版本:都指的是最後一個子元素節點(標籤)。
總結:爲了獲取最後一個子元素節點,咱們能夠這樣作:在IE678中用lastChild,在火狐谷歌IE9+之後用lastElementChild,因而,綜合這兩個屬性,能夠這樣寫:
最後一個子元素節點 = 節點.lastElementChild || 節點.lastChild
標準屬性。返回的是指定元素的子節點的集合(包括元素節點、全部屬性、文本節點)。是W3C的親兒子。
火狐 谷歌等高本版會把換行也看作是子節點。(瞭解)
用法:
子節點數組 = 父節點.childNodes; //獲取全部節點。
非標準屬性。返回的是指定元素的子元素節點的集合。【重要】
它只返回HTML節點,甚至不返回文本節點。
在IE6/7/8中包含註釋節點(在IE678中,註釋節點不要寫在裏面)。
雖然不是標準的DOM屬性,但它和innerHTML方法同樣,獲得了幾乎全部瀏覽器的支持。
用法:(用的最多)
子節點數組 = 父節點.children; //獲取全部節點。用的最多。
JS是以事件驅動爲核心的一門語言。
HTML 4.0 的新特性之一是有能力使 HTML 事件觸發瀏覽器中的動做(action),好比當用戶點擊某個 HTML 元素時啓動一段 JavaScript。下面是一個屬性列表,這些屬性可插入 HTML 標籤來定義事件動做。
常見事件以下:
onclick 當用戶點擊某個對象時調用的事件句柄。
ondblclick 當用戶雙擊某個對象時調用的事件句柄。
onfocus 元素得到焦點。 // 練習:輸入框
onblur 元素失去焦點。 應用場景:用於表單驗證,用戶離開某個輸入框時,表明已經輸入完了,咱們能夠對它進行驗證.
onchange 域的內容被改變。 應用場景:一般用於表單元素,當元素內容被改變時觸發.(select聯動)
onkeydown 某個鍵盤按鍵被按下。 應用場景: 當用戶在最後一個輸入框按下回車按鍵時,表單提交.
onkeypress 某個鍵盤按鍵被按下並鬆開。
onkeyup 某個鍵盤按鍵被鬆開。
onload 一張頁面或一幅圖像完成加載。
onmousedown 鼠標按鈕被按下。
onmousemove 鼠標被移動。
onmouseout 鼠標從某元素移開。
onmouseover 鼠標移到某元素之上。
onselect 在文本框中的文本被選中時發生。
onsubmit 確認按鈕被點擊,使用的對象是form。
事件的三要素:事件源、事件、事件驅動程序。
好比,我用手去按開關,燈亮了。這件事情裏,事件源是:手。事件是:按開關。事件驅動程序是:燈的開和關。
再好比,網頁上彈出一個廣告,我點擊右上角的X,廣告就關閉了。這件事情裏,事件源是:X。事件是:onclick。事件驅動程序是:廣告關閉了。
因而咱們能夠總結出:誰引起的後續事件,誰就是事件源。
總結以下:
事件源:引起後續事件的html標籤。
事件:js已經定義好了(見下圖)。
事件驅動程序:對樣式和html的操做。也就是DOM。
代碼書寫步驟以下:
獲取事件源:document.getElementById(「box」);
綁定事件: 事件源box.事件onclick = function(){ 事件驅動程序 };
書寫事件驅動程序:關於DOM的操做
代碼舉例一個事件例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
div{
width: 100px;
height: 100px;
background: green;
}
</style>
</head>
<body>
<div class="box" onclick="foo()"></div><!-- 方式三綁定事件 -->
<script>
// 1.獲取事件源
var div1 = document.getElementsByClassName("box")[0];
// 2.綁定事件
// 方式一:(經過匿名函數綁定,經常使用的)
div1.onclick = function () {
// 3.事件驅動程序
div1.style.backgroundColor = 'red';
};
// 方式二:
div1.onclick = foo; // 注意沒有括號
// 經過命名函數綁定
function foo() {
// 3.事件驅動程序
div1.style.backgroundColor = 'red';
}
</script>
</body>
</html>
下面針對這事件的三要素,進行分別介紹。
// 1.獲取事件源
var div1 = document.getElementsByClassName("box")[0];
<script>
var odiv = document.getElementById("box");
odiv.onclick = function(){
odiv.style.background = "red";
}
</script>
<script>
var odiv = document.getElementById("box");
odiv.onclick = fn; //注意,這裏是fn,不是fn()。fn()指的是返回值。
//單獨定義函數
function fn(){
odiv.style.background = "red";
}
</script>
// 行內綁定
<div id="box" onclick="fn()"></div>
// 注意第一行代碼,綁定時,是寫的"fn()",不是寫的"fn"。由於綁定的這段代碼不是寫在js代碼裏的,而是被識別成了字符串。
<script>
function fn(){
odiv.style.background = "red";
}
</script>
咱們上面的例子中改變背景顏色,就是事件驅動程序。
需求:
1. 默認盒子寬度和高度爲100px,背景色爲綠色;
2. 單擊後的效果爲盒子寬度和高度爲200px,背景色爲紅色;
3. 讓其上面的效果能夠來回進行切換。
html代碼:
<div class="box" ></div>
css樣式:
<style>
div{
width: 100px;
height: 100px;
background: green;
}
</style>
js代碼:
<script>
var div1 = document.getElementsByClassName("box")[0];
var flag = false;
div1.onclick = function () {
if (!flag) {
div1.style.width = "200px";
div1.style.height = "200px";
div1.style.backgroundColor = "red";
flag = true;
} else {
div1.style.width = "100px";
div1.style.height = "100px";
div1.style.backgroundColor = "green";
flag = false;
}
}
</script>
上方代碼的注意事項:
在js裏寫屬性值時,要用引號
在js裏寫屬性名時,是backgroundColor,不是CSS裏面的background-Color。
記得全部的像css屬性的text-*,line-*、backgroun-*等在js中都寫成駝峯。
當頁面加載(文本和圖片)完畢的時候,觸發onload事件。
舉例:
<head>
<script>
window.onload = function () {
console.log(111);
}
</script>
</head>
<body>
<script>
console.log(222);
</script>
</body>
有一點咱們要知道:js的加載是和html同步加載的。所以,若是使用元素在定義元素以前,容易報錯。這個時候,onload事件就能派上用場了,咱們能夠把使用元素的代碼放在onload裏,就能保證這段代碼是最後執行。
建議是:整個頁面上全部元素加載完畢在執行js內容。因此,window.onload能夠預防使用標籤在定義標籤以前。
案例一:盒子的顯示與隱藏
css樣式:
<style>
div {
width: 100px;
height: 100px;
background: green;
}
</style>
html內容:
<input type="text" id="input1" value="隱藏">
<button id="btn1">隱藏</button>
<div id="box"></div>
js代碼:
<script>
var oBtn = document.getElementById("btn1");
var oDiv = document.getElementById("box");
var oInput = document.getElementById("input1");
var flag = false;
oBtn.onclick = function () {
if (!flag){
oInput.value = "顯示";
oDiv.style.display = "none";
oBtn.innerText = "<span>顯示</span>";
flag = true;
}else{
//只進行賦值操做
oInput.value = "隱藏";
//事件驅動程序
oDiv.style.display = "block";
oBtn.innerHTML = "<span>隱藏</span>";
flag = false;
}
}
</script>
三個知識點:1.oInput.value 2.oBtn.innerText 3. oBtn.innerHTML
innerText 與innerHTML的區別在於,innerText直接將 "<span>顯示</span>"裏面的內容直接變成文本顯示,而innerHTML將 "<span>隱藏</span>"裏面的span內容語意話不顯示span,
以下效果圖:
innerText效果:
innerHTML效果:
案例二:
要求實現效果:
1. 當鼠標懸停在img上時,更換爲另一張圖片;
2. 鼠標離開時,還原爲原本的圖片。
<img src="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2121206715,2955288754&fm=26&gp=0.jpg" alt="" id="image">
<script>
var oImg = document.getElementById("image");
oImg.onmouseover = function () {
this.src = "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3488187566,3835668069&fm=26&gp=0.jpg";
};
oImg.onmouseout = function () {
this.src = "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2121206715,2955288754&fm=26&gp=0.jpg";
}
</script>
事件冒泡的條件:
必須是父子級關係。
必須是相同的綁定的方式(相同的事件)。
例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.father{
width: 500px;
height: 500px;
background: green;
}
.box1{
width: 300px;
height: 300px;
background: blue;
}
.box2{
width: 100px;
height: 100px;
background: red;
}
</style>
</head>
<body>
<div class="father">
<div class="box1">
<div class="box2"></div>
</div>
</div>
<script>
var father = document.getElementsByClassName("father")[0];
var box1 = document.getElementsByClassName("box1")[0];
var box2 = document.getElementsByClassName("box2")[0];
father.onclick = function () {
console.log("我是 father")
};
//加event防止冒泡
box1.onclick = function (event) {
event.stopPropagation();
console.log("我是 box1")
};
//function裏面加event阻止冒泡
//而後加event.stopPropagation();阻止冒泡
box2.onclick = function (event) {
event.stopPropagation();
console.log("我是 box2")
};
</script>
</body>
</html>
解決方法:
function裏面加event阻止冒泡
而後加event.stopPropagation();阻止冒泡
前面的內容:節點的訪問關係都是屬性。
節點的操做都是函數(方法)
格式以下:
新的標籤(元素節點) = 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>
相應的效果圖爲:
插入節點有兩種方式,它們的含義是不一樣的。
方式1:
父節點.appendChild(新的子節點);
解釋:父節點的最後插入一個新的子節點。
方式2:
父節點.insertBefore(新的子節點,做爲參考的子節點);
解釋:
在參考節點前插入一個新的節點。
若是參考節點爲null,那麼他將在父節點最後插入一個子節點。
格式以下:
父節點.removeChild(子節點);
解釋:用父節點刪除子節點。必需要指定是刪除哪一個子節點。
若是我想刪除本身這個節點,能夠這麼作:
node1.parentNode.removeChild(node1);
格式以下:
要複製的節點.cloneNode(); //括號裏不帶參數和帶參數false,效果是同樣的。
要複製的節點.cloneNode(true);
括號裏帶不帶參數,效果是不一樣的。解釋以下:
不帶參數/帶參數false:只複製節點自己,不復制子節點。
帶參數true:既複製節點自己,也複製其全部的子節點。
咱們能夠獲取節點的屬性值、設置節點的屬性值、刪除節點的屬性。
咱們就統一拿下面這個標籤來舉例:
<img src="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2121206715,2955288754&fm=26&gp=0.jpg"
class="image_box" title="美女圖片" alt="美女走丟了" id="a1">
下面分別介紹。
方式1:
元素節點.屬性;
元素節點[屬性];
舉例:(獲取節點的屬性值)
<script>
var myNode = document.getElementsByTagName("img")[0];
console.log(myNode.src);
console.log(myNode.className); //注意,是className,不是class
console.log(myNode.title);
console.log("------------");
console.log(myNode["src"]);
console.log(myNode["className"]); //注意,是className,不是class
console.log(myNode["title"]);
</script>
方式2:(推薦)
素節點.getAttribute("屬性名稱");
例子:
console.log(myNode.getAttribute("src"));
console.log(myNode.getAttribute("class")); //注意是class,不是className
console.log(myNode.getAttribute("title"));
方式1和方式2的區別在於:前者是直接操做標籤,後者是把標籤做爲DOM節點。推薦方式2
方式1:
舉例:(設置節點的屬性值)
myNode.src = "images/2.jpg" //修改src的屬性值
myNode.className = "image2-box"; //修改class的name
myNode['title'] = "漂亮嗎"; // 修改title的屬性值
方式2:(推薦)
元素節點.setAttribute(屬性名, 新的屬性值);
舉例:(設置節點的屬性值)
myNode.setAttribute("src","images/3.jpg");
myNode.setAttribute("class","image3-box");
myNode.setAttribute("id","aaa");
格式:
元素節點.removeAttribute(屬性名);
舉例:(刪除節點的屬性)
myNode.removeAttribute("class");
myNode.removeAttribute("id");
在js中的定時器分兩種:1、setTimeout() 2、setInterval()
只在指定時間後執行一次
<button id="btn1">開始</button>
<button id="btn2">清除</button>
<script>
var oBtn1 = document.getElementById("btn1");
var timer = null;
oBtn1.onclick = function () {
timer = setTimeout(function () {
console.log(1111);
console.log("我睡了三秒");
},3000)
};
var oBtn2 = document.getElementById("btn2");
oBtn2.onclick = function () {
clearTimeout(timer);
}
</script>
開始按完之後,只有按清除才能再按開始才能生效,反之同理。也就是上圖須要按完清除才能再打印出我睡了三秒
在指定時間爲週期循環執行
css樣式爲::
<style>
#box{
width: 100px;
height: 100px;
background: green;
}
</style>
html和js代碼爲:
<button id="start">開啓定時器</button>
<button id="stop">關閉定時器</button>
<div id="box"></div>
<script>
var strat = document.getElementById("start");
var box = document.getElementById("box");
var stop = document.getElementById("stop");
var margin_left = 0;
var timer = null;
strat.onclick = function () {
clearInterval(timer);
timer = setInterval(function () {
margin_left += 10;
box.style.marginLeft = margin_left + 'px';
}, 500)
};
stop.onclick = function () {
//清除定時器
clearInterval(timer);
}
</script>
兩種方法根據不一樣的場景和業務需求擇而取之,
對於這兩個方法,須要注意的是若是要求在每隔一個固定的時間間隔後就精確地執行某動做,那麼最好使用setInterval。
BOM:Browser Object Model,瀏覽器對象模型。
BOM的結構圖:
從上圖也能夠看出:
window對象是BOM的頂層(核心)對象,全部對象都是經過它延伸出來的,也能夠稱爲window的子對象。
DOM是BOM的一部分。
window對象:
window對象是JavaScript中的頂級對象。
全局變量、自定義函數也是window對象的屬性和方法。
window對象下的屬性和方法調用時,能夠省略window。
下面講一下 BOM 的常見內置方法和內置對象。
好比說,alert(1)是window.alert(1)的簡寫,由於它是window的子方法。
系統對話框有三種:
alert(); //不一樣瀏覽器中的外觀是不同的
confirm(); //兼容很差
prompt(); //不推薦使用
(1)打開窗口:
window.open(url,target)
參數解釋:
url:要打開的地址。
target:新窗口的位置。能夠是:_blank、_self、_parent 父框架。
例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<button>打開百度</button>
<button>關閉百度</button>
</body>
<script>
var oBtn = document.getElementsByTagName('button')[0];
var closeBtn = document.getElementsByTagName('button')[1];
var myWindow = null;
oBtn.onclick = function(){
myWindow = open('https://www.baidu.com');
//打開空白頁面
// open('about:blank',"_self") };
closeBtn.onclick = function(){
if(confirm("是否關閉?")){
myWindow.close();
}
}
</script>
</html>
window.location能夠簡寫成location。location至關於瀏覽器地址欄,能夠將url解析成獨立的片斷。
href:跳轉
hash 返回url中#後面的內容,包含#
host 主機名,包括端口
hostname 主機名
pathname url中的路徑部分
protocol 協議 通常是http、https
search 查詢字符串
location.href屬性舉例:
舉例:點擊盒子時,進行跳轉
例:
html和js代碼爲:
<body>
<div>點我</div>
<script>
var div = document.getElementsByTagName("div")[0];
div.onclick = function () {
location.href = "http://www.baidu.com"; //點擊div時,跳轉到指定連接
// window.open("http://www.baidu.com","_blank"); //方式二
}
</script>
</body>
(2)location對象的方法
location.reload():從新加載
setTimeout(function(){
//3秒以後讓網頁整個刷新
window.location.reload();
},3000)
history.back()
history.go(-1):0是刷新
history.forward()
history.go(1)
用的很少。由於瀏覽器中已經自帶了這些功能的按鈕
建立對象的幾種經常使用方式:
1.使用Object或對象字面量建立對象
2.工廠模式建立對象
3.構造函數模式建立對象
4.原型模式建立對象
(未完待續)