Web APIs
本篇學習目標:
能夠說出常用的3-5個鍵盤事件
能夠知道如何獲取當前鍵盤按下的是哪個鍵
能夠知道瀏覽器的頂級對象window
能夠使用window.onload事件
能夠使用window.onresize事件
能夠說出兩種定時器的區別
能夠使用location對象的href屬性完成頁面之間的跳轉
能夠使用location對象獲取url中的參數部分
能夠使用history提供的方法實現頁面刷新
1.1. 常用的鍵盤事件
1.1.1 鍵盤事件
<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>
1.1.2 鍵盤事件對象
使用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>
1.1.3 案例:模擬京東按鍵輸入內容
當我們按下 s 鍵, 光標就定位到搜索框(文本框獲得焦點)。
注意:觸發獲得焦點事件,可以使用 元素對象.focus()
<input type="text"><script>// 獲取輸入框var search = document.querySelector('input');// 給document注冊keyup事件document.addEventListener('keyup', function(e) {// 判斷keyCode的值if (e.keyCode === 83) {// 觸發輸入框的獲得焦點事件search.focus();}})</script>
1.1.4 案例:輸入銀行卡號,自動分割
要求:當我們在文本框中輸入內容時,文本框下面自動顯示分割后的銀行卡號。
<input type="text" name="" id="numbers"><div class="info"></div><script>var txt = document.querySelector('#numbers')var info = document.querySelector('.info')txt.addEventListener('keyup', function (e) {if (this.value.length > 4) {var result = ''for (var i = 0; i < this.value.length; i++) {var temp=i+1if (temp % 4 === 0 && temp!=0) {result += this.value[i] + ' '} else {result += this.value[i]}}info.innerHTML =result} else {info.innerHTML = this.value}})
延申練習:輸入了字母如何處理?
1.2. BOM
1.2.1. 什么是BOM
? BOM(Browser Object Model)即瀏覽器對象模型,它提供了獨立于內容而與瀏覽器窗口進行交互的對象,其核心對象是 window。
? BOM 由一系列相關的對象構成,并且每個對象都提供了很多方法與屬性。
? BOM 缺乏標準,JavaScript 語法的標準化組織是 ECMA,DOM 的標準化組織是 W3C,BOM 最初是Netscape 瀏覽器標準的一部分。
1.2.2. BOM的構成
BOM 比 DOM 更大,它包含 DOM。
1.2.3. 頂級對象window
1.2.4. window對象的常見事件
總結:到現在為止,學習到的事件分為兩類
1)需要用戶觸發的事件,比如前面學習的鼠標事件、鍵盤事件
2)不需要用戶觸發,而是程序在執行過程中自動觸發,開發者只需為其編寫事件處理程序即可
頁面(窗口)加載事件(2種)
第1種
window.onload 是窗口 (頁面)加載事件,當文檔內容完全加載完成會觸發該事件(包括圖像、腳本文件、CSS 文件等), 就調用的處理函數。
第2種
? DOMContentLoaded 事件觸發時,僅當DOM加載完成,不包括樣式表,圖片,flash等等。
? IE9以上才支持!!!
? 如果頁面的圖片很多的話, 從用戶訪問到onload觸發可能需要較長的時間, 交互效果就不能實現,必然影響用戶的體驗,此時用 DOMContentLoaded 事件比較合適。
<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>
調整窗口大小事件
? window.onresize 是調整窗口大小加載事件, 當觸發時就調用的處理函數。
注意:
-
只要窗口大小發生像素變化,就會觸發這個事件。
-
我們經常利用這個事件完成響應式布局。 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>
1.2.5. 定時器(兩種)
window 對象給我們提供了 2 個非常好用的方法-定時器。
-
setTimeout()
-
setInterval()
setTimeout() 炸彈定時器
開啟定時器
普通函數是按照代碼順序直接調用。簡單理解: 回調,就是回頭調用的意思。上一件事干完,再回頭再調用這個函數。 例如:定時器中的調用函數,事件處理函數,也是回調函數。以前我們講的 element.onclick = function(){} 或者 element.addEventListener(“click”, fn); 里面的 函數也是回調函數。
<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>
案例:倒計時
<div><span class="hour">1</span><span class="minute">2</span><span class="second">3</span></div><script>// 1. 獲取元素(時分秒盒子) var hour = document.querySelector('.hour'); // 小時的黑色盒子var minute = document.querySelector('.minute'); // 分鐘的黑色盒子var second = document.querySelector('.second'); // 秒數的黑色盒子var inputTime = +new Date('2020-5-1 18:00:00'); // 返回的是用戶輸入時間總的毫秒數countDown(); // 我們先調用一次這個函數,防止第一次刷新頁面有空白 // 2. 開啟定時器setInterval(countDown, 1000);function countDown() {var nowTime = +new Date(); // 返回的是當前時間總的毫秒數var times = (inputTime - nowTime) / 1000; // times是剩余時間總的秒數 var h = parseInt(times / 60 / 60); //時h = h < 10 ? '0' + h : h;hour.innerHTML = h; // 把剩余的小時給 小時黑色盒子var m = parseInt(times / 60 % 60); // 分m = m < 10 ? '0' + m : m;minute.innerHTML = m;var s = parseInt(times % 60); // 當前的秒s = s < 10 ? '0' + s : s;second.innerHTML = s;}</script>
停止定時器
案例:發送短信倒計時
? 點擊按鈕后,該按鈕60秒之內不能再次點擊,防止重復發送短信。
手機號碼: <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>
1.2.6. this指向問題
? this的指向在函數定義的時候是確定不了的,只有函數執行的時候才能確定this到底指向誰,一般情況下this的最終指向的是那個調用它的對象。
現階段,我們先了解一下幾個this指向
-
全局作用域或者普通函數中this指向全局對象window(注意定時器里面的this指向window)
-
方法調用中誰調用this指向誰
-
構造函數中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>
1.2.7. location對象
什么是 location 對象
URL
URL 就是常說的網址,專業的說:全球統一資源定位符
https://baike.baidu.com/m/24267858?fromtitle=新型冠狀病毒&fromid=7904360&fr=aladdin#link
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.baiduc.com';} else {div.innerHTML = '您將在' + timer + '秒鐘之后跳轉到首頁';timer--;}}, 1000);</script>
案例:獲取URL參數
// console.log(window.location)
console.log(location.search)
// 獲取參數部分
var search = location.search
// 從 “?” 后面開始截取
var params=search.substr(1)
console.log(params)// 根據“=”進行分割
var param_list=params.split('=')
console.log(param_list)
console.log(decodeURI(param_list[1]))
延申思考:如何傳遞多個參數?如何獲取多個參數,并輸出每個參數的值?如果傳遞的參數的值是中文,在獲取參數值是會發生什么情況?如何解決?請以此回答上面四個問題,并寫出案例
location對象的常見方法
<button>點擊</button><script>var btn = document.querySelector('button');btn.addEventListener('click', function() {// 記錄瀏覽歷史,所以可以實現后退功能// location.assign('https://baike.baidu.com/');// 不記錄瀏覽歷史,所以不可以實現后退功能// location.replace('https://baike.baidu.com/');location.reload(true);})</script>
1.2.8. 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 = ""; //電腦}
1.2.9 history對象
? window對象給我們提供了一個 history對象,與瀏覽器歷史記錄進行交互。該對象包含用戶(在瀏覽器窗口中)訪問過的URL。
history對象一般在實際開發中比較少用,但是會在一些 OA 辦公系統中見到。
1.3. JS執行機制
以下代碼執行的結果是什么?
console.log(1);setTimeout(function () {console.log(3);}, 1000);console.log(2);
以下代碼執行的結果是什么?
console.log(1);setTimeout(function () {console.log(3);}, 0);console.log(2);
1.3.1 JS 是單線程
單線程就意味著,所有任務需要排隊,前一個任務結束,才會執行后一個任務。如果前一個任務耗時很長,后一個任務就不得不一直等著。這樣所導致的問題是: 如果 JS 執行的時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染加載阻塞的感覺。
案例演示
在單線程中執行多個任務:同步任務
在多個線程中執行多個任務:異步任務
1.3.2 同步任務和異步任務
? 單線程導致的問題就是后面的任務等待前面任務完成,如果前面任務很耗時(比如讀取網絡數據),后面任務不得不一直等待!!
? 為了解決這個問題,利用多核 CPU 的計算能力,HTML5 提出 Web Worker 標準,允許 JavaScript 腳本創建多個線程,但是子線程完全受主線程控制。于是,JS 中出現了同步任務和異步任務。
同步
? 前一個任務結束后再執行后一個任務,程序的執行順序與任務的排列順序是一致的、同步的。比如做飯的同步做法:我們要燒水煮飯,等水開了(10分鐘之后),再去切菜,炒菜。
異步
? 你在做一件事情時,因為這件事情會花費很長時間,在做這件事的同時,你還可以去處理其他事情。比如做飯的異步做法,我們在燒水的同時,利用這10分鐘,去切菜,炒菜。
JS中所有任務可以分成兩種,一種是同步任務(synchronous),另一種是異步任務(asynchronous)。同步任務指的是:在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行后一個任務; 異步任務指的是:不進入主線程、而進入”任務隊列”的任務,當主線程中的任務運行完了,才會從”任務隊列”取出異步任務放入主線程執行。
1.3.3 JS執行機制(事件循環)
1.3.4 代碼思考題
console.log(1);document.onclick = function() {console.log('click');}setTimeout(function() {console.log(3)}, 3000)console.log(2);
再思考一個問題,下面代碼的執行結果是什么?說明什么問題
console.log(1); setTimeout(function () {console.log('ok')
}, 0)
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);
console.log(2);