前端學習之BOM與DOM
總結匯總一些常用的操作瀏覽器功能和頁面元素的API,如DOM文檔對象模型(Document Object Model)及BOM瀏覽器對象模型(Browser Object Model)等相關標準化的WebApi。
文章目錄
1. DOM樹操作
1.1 獲取元素
- 根據ID獲取
<body>
<div id="time">2019-9-9</div>
<script>
// 因爲我們文檔頁面從上往下加載,所以先得有標籤 所以我們script寫到標籤的下面
var timer = document.getElementById('time');
console.log(timer);
console.log(typeof timer);
// console.dir 打印我們返回的元素對象 更好的查看裏面的屬性和方法
console.dir(timer);
</script>
</body>
- 根據標籤名獲取元素
<body>
<ul>
<li>知否知否,應是等你好久11</li>
<li>知否知否,應是等你好久22</li>
</ul>
<ul id="nav">
<li>生僻字</li>
<li>生僻字</li>
</ul>
<script>
// 1.返回的是 獲取過來元素對象的集合 以僞數組的形式存儲的
var lis = document.getElementsByTagName('li');
console.log(lis);
console.log(lis[0]);
// 2. 我們想要依次打印裏面的元素對象我們可以採取遍歷的方式
for (var i = 0; i < lis.length; i++) {
console.log(lis[i]);
}
// 3. element.getElementsByTagName() 可以得到這個元素裏面的某些標籤
var nav = document.getElementById('nav'); // 這個獲得nav 元素
var navLis = nav.getElementsByTagName('li');
console.log(navLis);
</script>
</body>
- H5新增獲取元素方式
<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>首頁</li>
<li>產品</li>
</ul>
</div>
<script>
// 1. getElementsByClassName 根據類名獲得某些元素集合
var boxs = document.getElementsByClassName('box');
console.log(boxs);
// 2. querySelector 返回指定選擇器的第一個元素對象 切記 裏面的選擇器需要加符號 .box #nav
var firstBox = document.querySelector('.box');
console.log(firstBox);
var nav = document.querySelector('#nav');
console.log(nav);
var li = document.querySelector('li');
console.log(li);
// 3. querySelectorAll()返回指定選擇器的所有元素對象集合
var allBox = document.querySelectorAll('.box');
console.log(allBox);
var lis = document.querySelectorAll('li');
console.log(lis);
document.body // 返回body元素
document.documentElement // 返回html元素對象
</script>
</body>
1.2 事件基礎
<body>
<div>123</div>
<script>
// 執行事件步驟
// 點擊div 控制檯輸出 我被選中了
// 1. 獲取事件源
var div = document.querySelector('div');
// 2.綁定事件 註冊事件
// div.onclick
// 3.添加事件處理程序
div.onclick = function() {
console.log('我被選中了');
}
</script>
</body>
1.3 改變元素內容
<body>
<div></div>
<p>
我是文字
<span>123</span>
</p>
<script>
// innerText 和 innerHTML的區別
// 1. innerText 不識別html標籤 非標準 去除空格和換行
var div = document.querySelector('div');
// div.innerText = '<strong>今天是:</strong> 2019';
// 2. innerHTML 識別html標籤 W3C標準 保留空格和換行的
div.innerHTML = '<strong>今天是:</strong> 2019';
// 這兩個屬性是可讀寫的 可以獲取元素裏面的內容
var p = document.querySelector('p');
console.log(p.innerText);
console.log(p.innerHTML);
</script>
</body>
1.4 常用元素的屬性操作
<body>
<button id="ldh">劉德華</button>
<button id="zxy">張學友</button> <br>
<img src="images/ldh.jpg" alt="" title="劉德華">
<script>
// 修改元素屬性 src
// 1. 獲取元素
var ldh = document.getElementById('ldh');
var zxy = document.getElementById('zxy');
var img = document.querySelector('img');
// 2. 註冊事件 處理程序
zxy.onclick = function() {
img.src = 'images/zxy.jpg';
img.title = '張學友思密達';
}
ldh.onclick = function() {
img.src = 'images/ldh.jpg';
img.title = '劉德華';
}
// 1. 獲取元素
var btn = document.querySelector('button');
var input = document.querySelector('input');
// 2. 註冊事件 處理程序
btn.onclick = function() {
// 表單裏面的值 文字內容是通過 value 來修改的
input.value = '被點擊了';
// 如果想要某個表單被禁用 不能再點擊 disabled 我們想要這個按鈕 button禁用
// btn.disabled = true;
this.disabled = true;
// this 指向的是事件函數的調用者 btn
}
</script>
</body>
1.5 樣式屬性操作
<body>
<div></div>
<script>
// 1. 獲取元素
var div = document.querySelector('div');
// 2. 註冊事件 處理程序
div.onclick = function() {
// div.style裏面的屬性 採取駝峯命名法
this.style.backgroundColor = 'purple';
this.style.width = '250px';
this.className = '';
// this.style.backgroundColor = 'purple';
// this.style.color = '#fff';
// this.style.fontSize = '25px';
// this.style.marginTop = '100px';
// 2. 我們可以通過 修改元素的className更改元素的樣式 適合於樣式較多或者功能複雜的情況
// 3. 如果想要保留原先的類名,我們可以這麼做 多類名選擇器
// this.className = 'change';
this.className = 'first change';
}
</script>
</body>
1.6 自定義屬性操作
<div id="demo" index="1" class="nav"></div>
<script>
var div = document.querySelector('div');
// 1. 獲取元素的屬性值
// (1) element.屬性
console.log(div.id);
//(2) element.getAttribute('屬性') get得到獲取 attribute 屬性的意思 我們程序員自己添加的屬性我們稱爲自定義屬性 index
console.log(div.getAttribute('id'));
console.log(div.getAttribute('index'));
// 2. 設置元素屬性值
// (1) element.屬性= '值'
div.id = 'test';
div.className = 'navs';
// (2) element.setAttribute('屬性', '值'); 主要針對於自定義屬性
div.setAttribute('index', 2);
div.setAttribute('class', 'footer'); // class 特殊,不是className
// 3. 移除屬性 removeAttribute(屬性)
div.removeAttribute('index');
</script>
1.7 H5自定義屬性
<div getTime="20" data-index="2" data-list-name="andy"></div>
<script>
var div = document.querySelector('div');
// console.log(div.getTime);
console.log(div.getAttribute('getTime'));
div.setAttribute('data-time', 20);
console.log(div.getAttribute('data-index'));
console.log(div.getAttribute('data-list-name'));
// h5新增的獲取自定義屬性的方法 它只能獲取data-開頭的
// dataset 是一個集合裏面存放了所有以data開頭的自定義屬性
console.log(div.dataset);
console.log(div.dataset.index);
console.log(div.dataset['index']);
// 如果自定義屬性裏面有多個-鏈接的單詞,我們獲取的時候採取 駝峯命名法
console.log(div.dataset.listName);
console.log(div.dataset['listName']);
</script>
1.8 節點操作
// 父節點
<div class="demo">
<div class="box">
<span class="erweima">×</span>
</div>
</div>
<script>
// 1. 父節點 parentNode
var erweima = document.querySelector('.erweima');
// var box = document.querySelector('.box');
// 得到的是離元素最近的父級節點(親爸爸) 如果找不到父節點就返回爲 null
console.log(erweima.parentNode);
</script>
// 子節點
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<script>
// DOM 提供的方法(API)獲取
var ul = document.querySelector('ul');
var lis = ul.querySelectorAll('li');
// 1. 子節點 childNodes 所有的子節點 包含 元素節點 文本節點等等
console.log(ul.childNodes);
console.log(ul.childNodes[0].nodeType);
console.log(ul.childNodes[1].nodeType);
// 2. children 獲取所有的子元素節點 也是我們實際開發常用的
console.log(ul.children);
</script>
<ol>
<li>我是li1</li>
<li>我是li2</li>
<li>我是li3</li>
<li>我是li4</li>
<li>我是li5</li>
</ol>
<script>
var ol = document.querySelector('ol');
// 1. firstChild 第一個子節點 不管是文本節點還是元素節點
console.log(ol.firstChild);
console.log(ol.lastChild);
// 2. firstElementChild 返回第一個子元素節點 ie9才支持
console.log(ol.firstElementChild);
console.log(ol.lastElementChild);
// 3. 實際開發的寫法 既沒有兼容性問題又返回第一個子元素
console.log(ol.children[0]);
console.log(ol.children[ol.children.length - 1]);
</script>
// 兄弟節點
<div>我是div</div>
<span>我是span</span>
<script>
var div = document.querySelector('div');
// 1.nextSibling 下一個兄弟節點 包含元素節點或者 文本節點等等
console.log(div.nextSibling);
console.log(div.previousSibling);
// 2. nextElementSibling 得到下一個兄弟元素節點
console.log(div.nextElementSibling);
console.log(div.previousElementSibling);
</script>
// 創建添加節點
<ul>
<li>123</li>
</ul>
<script>
// 1. 創建節點元素節點
var li = document.createElement('li');
// 2. 添加節點 node.appendChild(child) node 父級 child 是子級 後面追加元素
var ul = document.querySelector('ul');
ul.appendChild(li);
// 3. 添加節點 node.insertBefore(child, 指定元素);
var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);
// 4. 我們想要頁面添加一個新的元素 : 1. 創建元素 2. 添加元素
</script>
// 刪除節點
<button>刪除</button>
<ul>
<li>熊大</li>
<li>熊二</li>
<li>光頭強</li>
</ul>
<script>
// 1.獲取元素
var ul = document.querySelector('ul');
var btn = document.querySelector('button');
// 2. 刪除元素 node.removeChild(child)
// ul.removeChild(ul.children[0]);
// 3. 點擊按鈕依次刪除裏面的孩子
btn.onclick = function() {
if (ul.children.length == 0) {
this.disabled = true;
} else {
ul.removeChild(ul.children[0]);
}
}
</script>
// 複製(克隆)節點
<ul>
<li>1111</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector('ul');
// 1. node.cloneNode(); 括號爲空或者裏面是false 淺拷貝 只複製標籤不復制裏面的內容
// 2. node.cloneNode(true); 括號爲true 深拷貝 複製標籤複製裏面的內容
var lili = ul.children[0].cloneNode(true);
ul.appendChild(lili);
</script>
1.9 創建元素的三種方式
<script>
// 三種創建元素方式區別
// 1. document.write() 創建元素 如果頁面文檔流加載完畢,再調用這句話會導致頁面重繪
var btn = document.querySelector('button');
btn.onclick = function() {
document.write('<div>123</div>');
}
// 2. innerHTML 創建元素
var inner = document.querySelector('.inner');
for (var i = 0; i <= 100; i++) {
inner.innerHTML += '<a href="#">百度</a>'
}
var arr = [];
for (var i = 0; i <= 100; i++) {
arr.push('<a href="#">百度</a>');
}
inner.innerHTML = arr.join('');
// 3. document.createElement() 創建元素
var create = document.querySelector('.create');
for (var i = 0; i <= 100; i++) {
var a = document.createElement('a');
create.appendChild(a);
}
</script>
// innerTHML和createElement效率對比
// 1. innerHTML字符串拼接方式(效率低)
<script>
function fn() {
var d1 = +new Date();
var str = '';
for (var i = 0; i < 1000; i++) {
document.body.innerHTML += '<div style="width:100px; height:2px; border:1px solid blue;"></div>';
}
var d2 = +new Date();
console.log(d2 - d1);
}
fn();
</script>
// 2. createElement方式(效率一般)
<script>
function fn() {
var d1 = +new Date();
for (var i = 0; i < 1000; i++) {
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '2px';
div.style.border = '1px solid red';
document.body.appendChild(div);
}
var d2 = +new Date();
console.log(d2 - d1);
}
fn();
</script>
// 3. innerHTML數組方式(效率高)
<script>
function fn() {
var d1 = +new Date();
var array = [];
for (var i = 0; i < 1000; i++) {
array.push('<div style="width:100px; height:2px; border:1px solid blue;"></div>');
}
document.body.innerHTML = array.join('');
var d2 = +new Date();
console.log(d2 - d1);
}
fn();
</script>
1.91 事件高級
1.91.1 事件監聽
addEventListener()事件監聽(IE9以後支持)
attacheEvent()事件監聽(IE678支持)
<button>傳統註冊事件</button>
<button>方法監聽註冊事件</button>
<button>ie9 attachEvent</button>
<script>
var btns = document.querySelectorAll('button');
// 1. 傳統方式註冊事件
btns[0].onclick = function() {
alert('hi');
}
btns[0].onclick = function() {
alert('hao a u');
}
// 2. 事件偵聽註冊事件 addEventListener
// (1) 裏面的事件類型是字符串 必定加引號 而且不帶on
// (2) 同一個元素 同一個事件可以添加多個偵聽器(事件處理程序)
btns[1].addEventListener('click', function() {
alert(22);
})
btns[1].addEventListener('click', function() {
alert(33);
})
// 3. attachEvent ie9以前的版本支持
btns[2].attachEvent('onclick', function() {
alert(11);
})
</script>
1.91.2 刪除事件(解綁事件)
<div>1</div>
<div>2</div>
<div>3</div>
<script>
var divs = document.querySelectorAll('div');
divs[0].onclick = function() {
alert(11);
// 1. 傳統方式刪除事件
divs[0].onclick = null;
}
// 2. removeEventListener 刪除事件
divs[1].addEventListener('click', fn) // 裏面的fn 不需要調用加小括號
function fn() {
alert(22);
divs[1].removeEventListener('click', fn);
}
// 3. detachEvent
divs[2].attachEvent('onclick', fn1);
function fn1() {
alert(33);
divs[2].detachEvent('onclick', fn1);
}
</script>
1.91.3 事件冒泡與捕獲
// 事件冒泡
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
// onclick 和 attachEvent(ie) 在冒泡階段觸發
// 冒泡階段 如果addEventListener 第三個參數是 false 或者 省略
// son -> father ->body -> html -> document
var son = document.querySelector('.son');
// 給son註冊單擊事件
son.addEventListener('click', function() {
alert('son');
}, false);
// 給father註冊單擊事件
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
// 給document註冊單擊事件,省略第3個參數
document.addEventListener('click', function() {
alert('document');
})
</script>
// 事件捕獲
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
// 如果addEventListener() 第三個參數是 true 那麼在捕獲階段觸發
// document -> html -> body -> father -> son
var son = document.querySelector('.son');
// 給son註冊單擊事件,第3個參數爲true
son.addEventListener('click', function() {
alert('son');
}, true);
var father = document.querySelector('.father');
// 給father註冊單擊事件,第3個參數爲true
father.addEventListener('click', function() {
alert('father');
}, true);
// 給document註冊單擊事件,第3個參數爲true
document.addEventListener('click', function() {
alert('document');
}, true)
</script>
1.91.4 事件對象
事件發生後,跟事件相關的一系列信息數據的集合都放到這個對象裏面,這個對象就是事件對象。
誰綁定了這個事件,鼠標觸發事件的話,會得到鼠標的相關信息,如鼠標位置,鍵盤觸發事件的話,會得到鍵盤的相關信息,如按了哪個鍵。事件觸發發生時就會產生事件對象,並且系統會以實參的形式傳給事件處理函數。所以,在事件處理函數中聲明1個形參用來接收事件對象。
- 事件對象的兼容性處理
事件對象本身的獲取存在兼容問題:
1.標準瀏覽器中是瀏覽器給方法傳遞的參數,只需要定義形參 e 就可以獲取到。
2.在 IE6~8 中,瀏覽器不會給方法傳遞參數,如果需要的話,需要到 window.event 中獲取查找。
只要“||”前面爲false, 不管“||”後面是true 還是 false,都返回 “||” 後面的值。
只要“||”前面爲true, 不管“||”後面是true 還是 false,都返回 “||” 前面的值。
<div>123</div>
<script>
var div = document.querySelector('div');
div.onclick = function(e) {
// 事件對象
e = e || window.event;
console.log(e);
}
</script>
- e.target 和 this 的區別
this 是事件綁定的元素(綁定這個事件處理函數的元素) 。e.target 是事件觸發的元素。常情況下terget 和 this是一致的,但有一種情況不同,那就是在事件冒泡時(父子元素有相同事件,單擊子元素,父元素的事件處理函數也會被觸發執行),這時候this指向的是父元素,因爲它是綁定事件的元素對象,而target指向的是子元素,因爲他是觸發事件的那個具體元素對象。
<div>123</div>
<script>
var div = document.querySelector('div');
div.addEventListener('click', function(e) {
// e.target 和 this指向的都是div
console.log(e.target);
console.log(this);
});
</script>
- 事件冒泡下的e.target和this
<ul>
<li>abc</li>
<li>abc</li>
<li>abc</li>
</ul>
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
// 我們給ul 綁定了事件 那麼this 就指向ul
console.log(this); // ul
// e.target 觸發了事件的對象 我們點擊的是li e.target 指向的就是li
console.log(e.target); // li
});
</script>
- 阻止默認行爲
html中一些標籤有默認行爲,例如a標籤被單擊後,默認會進行頁面跳轉。
<a href="http://www.baidu.com">百度</a>
<script>
// 2. 阻止默認行爲 讓鏈接不跳轉
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
e.preventDefault(); // dom 標準寫法
});
// 3. 傳統的註冊方式
a.onclick = function(e) {
// 普通瀏覽器 e.preventDefault(); 方法
e.preventDefault();
// 低版本瀏覽器 ie678 returnValue 屬性
e.returnValue = false;
// 我們可以利用return false 也能阻止默認行爲 沒有兼容性問題
return false;
}
</script>
- 阻止事件冒泡
<div class="father">
<div class="son">son兒子</div>
</div>
<script>
var son = document.querySelector('.son');
// 給son註冊單擊事件
son.addEventListener('click', function(e) {
alert('son');
e.stopPropagation(); // stop停止Propagation 傳播
window.event.cancelBubble = true; // 非標準 cancel 取消 bubble 泡泡
}, false);
var father = document.querySelector('.father');
// 給father註冊單擊事件
father.addEventListener('click', function() {
alert('father');
}, false);
// 給document註冊單擊事件
document.addEventListener('click', function() {
alert('document');
})
</script>
1.91.5 事件委託
事件委託也稱爲事件代理,在 jQuery 裏面稱爲事件委派。不給子元素註冊事件,給父元素註冊事件,把處理代碼在父元素的事件中執行。給父元素註冊事件,利用事件冒泡,當子元素的事件觸發,會冒泡到父元素,然後去控制相應的子元素。
- 事件委託的作用
我們只操作了一次 DOM ,提高了程序的性能。動態新創建的子元素,也擁有事件。
<ul>
<li>知否知否,點我應有彈框在手!</li>
<li>知否知否,點我應有彈框在手!</li>
<li>知否知否,點我應有彈框在手!</li>
<li>知否知否,點我應有彈框在手!</li>
<li>知否知否,點我應有彈框在手!</li>
</ul>
<script>
// 事件委託的核心原理:給父節點添加偵聽器, 利用事件冒泡影響每一個子節點
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
// e.target 這個可以得到我們點擊的對象
e.target.style.backgroundColor = 'pink';
})
</script>
1.91.6 鼠標事件
- 禁止選中文字和禁止右鍵菜單
<body>
我是一段不願意分享的文字
<script>
// 1. contextmenu 我們可以禁用右鍵菜單
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
// 2. 禁止選中文字 selectstart
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
</script>
</body>
- 獲取鼠標在頁面的座標
<script>
// 鼠標事件對象 MouseEvent
document.addEventListener('click', function(e) {
// 1. client 鼠標在可視區的x和y座標
console.log(e.clientX);
console.log(e.clientY);
console.log('---------------------');
// 2. page 鼠標在頁面文檔的x和y座標
console.log(e.pageX);
console.log(e.pageY);
console.log('---------------------');
// 3. screen 鼠標在電腦屏幕的x和y座標
console.log(e.screenX);
console.log(e.screenY);
})
</script>
1.91.7 鍵盤事件
<script>
// 常用的鍵盤事件
//1. keyup 按鍵彈起的時候觸發
document.addEventListener('keyup', function() {
console.log('我彈起了');
})
//3. keypress 按鍵按下的時候觸發 不能識別功能鍵 比如 ctrl shift 左右箭頭啊
document.addEventListener('keypress', function() {
console.log('我按下了press');
})
//2. keydown 按鍵按下的時候觸發 能識別功能鍵 比如 ctrl shift 左右箭頭啊
document.addEventListener('keydown', function() {
console.log('我按下了down');
})
// 4. 三個事件的執行順序 keydown -- keypress -- keyup
</script>
- 使用keyCode屬性判斷用戶按下哪個鍵**
<script>
// 鍵盤事件對象中的keyCode屬性可以得到相應鍵的ASCII碼值
document.addEventListener('keyup', function(e) {
console.log('up:' + e.keyCode);
// 我們可以利用keycode返回的ASCII碼值來判斷用戶按下了那個鍵
if (e.keyCode === 65) {
alert('您按下的a鍵');
} else {
alert('您沒有按下a鍵')
}
})
document.addEventListener('keypress', function(e) {
// console.log(e);
console.log('press:' + e.keyCode);
})
</script>
2. BOM瀏覽器對象模型
BOM(Browser Object Model)即瀏覽器對象模型,它提供了獨立於內容而與瀏覽器窗口進行交互的對象,其核心對象是 window。BOM 由一系列相關的對象構成,並且每個對象都提供了很多方法與屬性。BOM 缺乏標準,JavaScript 語法的標準化組織是 ECMA,DOM 的標準化組織是 W3C,BOM 最初是Netscape 瀏覽器標準的一部分。
2.1 頂級對象window
2.1.1 頁面(窗口)加載事件
window.onload 是窗口 (頁面)加載事件,當文檔內容完全加載完成會觸發該事件(包括圖像、腳本文件、CSS 文件等), 就調用的處理函數。DOMContentLoaded 事件觸發時,僅當DOM加載完成,不包括樣式表,圖片,flash等等。IE9以上才支持。
<script>
window.addEventListener('load', function() {
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
alert('點擊我');
})
})
window.addEventListener('load', function() {
alert(22);
})
document.addEventListener('DOMContentLoaded', function() {
alert(33);
})
</script>
2.1.2 調整窗口大小事件
window.onresize 是調整窗口大小加載事件, 當觸發時就調用的處理函數。1.只要窗口大小發生像素變化,就會觸發這個事件。2.我們經常利用這個事件完成響應式佈局。 window.innerWidth 當前屏幕的寬度
<script>
// 註冊頁面加載事件
window.addEventListener('load', function() {
var div = document.querySelector('div');
// 註冊調整窗口大小事件
window.addEventListener('resize', function() {
// window.innerWidth 獲取窗口大小
console.log('變化了');
if (window.innerWidth <= 800) {
div.style.display = 'none';
} else {
div.style.display = 'block';
}
})
})
</script>
<div></div>
2.1.3 定時器(兩種)
window 對象給我們提供了 2 個非常好用的方法-定時器。 setTimeout() 和 setInterval()
<script>
// 回調函數是一個匿名函數
setTimeout(function() {
console.log('時間到了');
}, 2000);
function callback() {
console.log('爆炸了');
}
// 回調函數是一個有名函數
var timer1 = setTimeout(callback, 3000);
var timer2 = setTimeout(callback, 5000);
</script>
// 5秒後關閉一個廣告
<body>
<img src="images/ad.jpg" alt="" class="ad">
<script>
// 獲取要操作的元素
var ad = document.querySelector('.ad');
// 開啓定時器
setTimeout(function() {
ad.style.display = 'none';
}, 5000);
</script>
</body>
<button>點擊停止定時器</button>
<script>
var btn = document.querySelector('button');
// 開啓定時器
var timer = setTimeout(function() {
console.log('爆炸了');
}, 5000);
// 給按鈕註冊單擊事件
btn.addEventListener('click', function() {
// 停止定時器
clearTimeout(timer);
})
</script>
// setInterval() 鬧鐘定時器
<script>
// 1. setInterval
setInterval(function() {
console.log('繼續輸出');
}, 1000);
</script>
// clearInterval(timer)停止定時器
手機號碼: <input type="number"> <button>發送</button>
<script>
var btn = document.querySelector('button');
// 全局變量,定義剩下的秒數
var time = 3;
// 註冊單擊事件
btn.addEventListener('click', function() {
// 禁用按鈕
btn.disabled = true;
// 開啓定時器
var timer = setInterval(function() {
// 判斷剩餘秒數
if (time == 0) {
// 清除定時器和復原按鈕
clearInterval(timer);
btn.disabled = false;
btn.innerHTML = '發送';
} else {
btn.innerHTML = '還剩下' + time + '秒';
time--;
}
}, 1000);
});
</script>
2.1.4 this指向問題
this的指向在函數定義的時候是確定不了的,只有函數執行的時候才能確定this到底指向誰,一般情況下this的最終指向的是那個調用它的對象。
1.全局作用域或者普通函數中this指向全局對象window(注意定時器裏面的this指向window)
2.方法調用中誰調用this指向誰
3.構造函數中this指向構造函數的實例
<button>點擊</button>
<script>
// this 指向問題 一般情況下this的最終指向的是那個調用它的對象
// 1. 全局作用域或者普通函數中this指向全局對象window( 注意定時器裏面的this指向window)
console.log(this);
function fn() {
console.log(this);
}
window.fn();
window.setTimeout(function() {
console.log(this);
}, 1000);
// 2. 方法調用中誰調用this指向誰
var o = {
sayHi: function() {
console.log(this); // this指向的是 o 這個對象
}
}
o.sayHi();
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
console.log(this); // 事件處理函數中的this指向的是btn這個按鈕對象
})
// 3. 構造函數中this指向構造函數的實例
function Fun() {
console.log(this); // this 指向的是fun 實例對象
}
var fun = new Fun();
</script>
2.2 location對象
// 5分鐘自動跳轉頁面
<button>點擊</button>
<div></div>
<script>
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.addEventListener('click', function() {
// console.log(location.href);
location.href = 'http://www.itcast.cn';
})
var timer = 5;
setInterval(function() {
if (timer == 0) {
location.href = 'http://www.itcast.cn';
} else {
div.innerHTML = '您將在' + timer + '秒鐘之後跳轉到首頁';
timer--;
}
}, 1000);
</script>
// 獲取URL參數
<div></div>
<script>
console.log(location.search); // ?uname=andy
// 1.先去掉? substr('起始的位置',截取幾個字符);
var params = location.search.substr(1); // uname=andy
console.log(params);
// 2. 利用=把字符串分割爲數組 split('=');
var arr = params.split('=');
console.log(arr); // ["uname", "ANDY"]
var div = document.querySelector('div');
// 3.把數據寫入div中
div.innerHTML = arr[1] + '歡迎您';
</script>
<button>點擊</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
// 記錄瀏覽歷史,所以可以實現後退功能
// location.assign('http://www.itcast.cn');
// 不記錄瀏覽歷史,所以不可以實現後退功能
// location.replace('http://www.itcast.cn');
location.reload(true);
})
</script>
2.3 navigator對象
navigator 對象包含有關瀏覽器的信息,它有很多屬性,我們最常用的是 userAgent,該屬性可以返回由客戶機發送服務器的 user-agent 頭部的值。下面前端代碼可以判斷用戶那個終端打開頁面,實現跳轉。
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = ""; //手機
} else {
window.location.href = ""; //電腦
}
2.3 history對象
window對象給我們提供了一個 history對象,與瀏覽器歷史記錄進行交互。該對象包含用戶(在瀏覽器窗口中)訪問過的URL。
back() //後退
forward() // 前進
go(參數) // 1:前進一個頁面 -1: 後對一個頁面
3. Js執行機制
JS 是單線程的, 單線程就意味着,所有任務需要排隊,前一個任務結束,纔會執行後一個任務。如果前一個任務耗時很長,後一個任務就不得不一直等着。這樣所導致的問題是: 如果 JS 執行的時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染加載阻塞的感覺。 爲了解決這個問題,利用多核 CPU 的計算能力,HTML5 提出 Web Worker 標準,允許 JavaScript 腳本創建多個線程,但是子線程完全受主線程控制。於是,JS 中出現了同步任務和異步任務。
4. offset/client/scroll
1.元素偏移量offset系列 經常用於獲得元素位置 offsetLeft offsetTop
offset 與 style 區別
- offset 可以得到任意樣式表中的樣式值
- offset 系列獲得的數值是沒有單位的
- offsetWidth 包含padding+border+width
- offsetWidth 等屬性是隻讀屬性,只能獲取不能賦值
所以,我們想要獲取元素大小位置,用offset更合適 - style 只能得到行內樣式表中的樣式值
- style.width 獲得的是帶有單位的字符串
- style.width 獲得不包含padding和border 的值
- style.width 是可讀寫屬性,可以獲取也可以賦值
所以,我們想要給元素更改值,則需要用style改變
2.元素可視區client經常用於獲取元素大小 clientWidth clientHeight
client 翻譯過來就是客戶端,我們使用 client 系列的相關屬性來獲取元素可視區的相關信息。通過 client系列的相關屬性可以動態的得到該元素的邊框大小、元素大小等。
3.元素滾動scroll 經常用於獲取滾動距離 scrollTop scrollLeft
scroll 翻譯過來就是滾動的,我們使用 scroll 系列的相關屬性可以動態的得到該元素的大小、滾動距離等。
4.注意頁面滾動的距離通過 window.pageXOffset 獲得
5. mouseenter 和mouseover的區別
- 當鼠標移動到元素上時就會觸發mouseenter 事件
- 類似 mouseover,它們兩者之間的差別是
- mouseover 鼠標經過自身盒子會觸發,經過子盒子還會觸發。mouseenter 只會經過自身盒子觸發
- 之所以這樣,就是因爲mouseenter不會冒泡
- 跟mouseenter搭配鼠標離開 mouseleave 同樣不會冒泡
6. 觸屏事件
touchstart、touchmove、touchend可以實現拖動元素
但是拖動元素需要當前手指的座標值 我們可以使用 targetTouches[0] 裏面的pageX 和 pageY
移動端拖動的原理:
手指移動中,計算出手指移動的距離。然後用盒子原來的位置 + 手指移動的距離
手指移動的距離: 手指滑動中的位置 減去 手指剛開始觸摸的位置
拖動元素三步曲:
(1) 觸摸元素 touchstart: 獲取手指初始座標,同時獲得盒子原來的位置
(2) 移動手指 touchmove: 計算手指的滑動距離,並且移動盒子
(3) 離開手指 touchend:
手指移動也會觸發滾動屏幕所以這裏要阻止默認的屏幕滾動 e.preventDefault();
7. 本地存儲
隨着互聯網的快速發展,基於網頁的應用越來越普遍,同時也變的越來越複雜,爲了滿足各種各樣的需求,會經常性在本地存儲大量的數據,HTML5規範提出了相關解決方案。
- 本地存儲特性
1、數據存儲在用戶瀏覽器中
2、設置、讀取方便、甚至頁面刷新不丟失數據
3、容量較大,sessionStorage約5M、localStorage約20M
4、只能存儲字符串,可以將對象JSON.stringify() 編碼後存儲
- window.sessionStorage
1、生命週期爲關閉瀏覽器窗口
2、在同一個窗口(頁面)下數據可以共享
3、以鍵值對的形式存儲使用
sessionStorage.setItem(key, value)
sessionStorage.getItem(key)
sessionStorage.removeItem(key)
sessionStorage.clear()
- window.localStorage
1、聲明週期永久生效,除非手動刪除 否則關閉頁面也會存在
2、可以多窗口(頁面)共享(同一瀏覽器可以共享)
3、 以鍵值對的形式存儲使用
localStorage.setItem(key, value)
localStorage.getItem(key)
localStorage.removeItem(key)
localStorage.clear()