Web APIs(四)
1.1. 常用的鍵盤事件
1.1.1 鍵盤事件
<script>
// 常用的鍵盤事件
//1. keyup 按鍵彈起的時候觸發(fā)
document.addEventListener('keyup', function() {
console.log('我彈起了');
})
//3. keypress 按鍵按下的時候觸發(fā) 不能識別功能鍵 比如 ctrl shift 左右箭頭啊
document.addEventListener('keypress', function() {
console.log('我按下了press');
})
//2. keydown 按鍵按下的時候觸發(fā) 能識別功能鍵 比如 ctrl shift 左右箭頭啊
document.addEventListener('keydown', function() {
console.log('我按下了down');
})
// 4. 三個事件的執(zhí)行順序 keydown -- keypress -- keyup
</script>
1.1.2 鍵盤事件對象
使用keyCode屬性判斷用戶按下哪個鍵
<script>
// 鍵盤事件對象中的keyCode屬性可以得到相應(yīng)鍵的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 案例:模擬京東按鍵輸入內(nèi)容
當我們按下 s 鍵, 光標就定位到搜索框(文本框獲得焦點)番枚。
注意:觸發(fā)獲得焦點事件蝗锥,可以使用 元素對象.focus()
<input type="text">
<script>
// 獲取輸入框
var search = document.querySelector('input');
// 給document注冊keyup事件
document.addEventListener('keyup', function(e) {
// 判斷keyCode的值
if (e.keyCode === 83) {
// 觸發(fā)輸入框的獲得焦點事件
search.focus();
}
})
</script>
1.1.4 案例:模擬京東快遞單號查詢
要求:當我們在文本框中輸入內(nèi)容時喘帚,文本框上面自動顯示大字號的內(nèi)容诡壁。
<div class="search">
<div class="con">123</div>
<input type="text" placeholder="請輸入您的快遞單號" class="jd">
</div>
<script>
// 獲取要操作的元素
var con = document.querySelector('.con');
var jd_input = document.querySelector('.jd');
// 給輸入框注冊keyup事件
jd_input.addEventListener('keyup', function() {
// 判斷輸入框內(nèi)容是否為空
if (this.value == '') {
// 為空障贸,隱藏放大提示盒子
con.style.display = 'none';
} else {
// 不為空炼吴,顯示放大提示盒子味滞,設(shè)置盒子的內(nèi)容
con.style.display = 'block';
con.innerText = this.value;
}
})
// 給輸入框注冊失去焦點事件,隱藏放大提示盒子
jd_input.addEventListener('blur', function() {
con.style.display = 'none';
})
// 給輸入框注冊獲得焦點事件
jd_input.addEventListener('focus', function() {
// 判斷輸入框內(nèi)容是否為空
if (this.value !== '') {
// 不為空則顯示提示盒子
con.style.display = 'block';
}
})
</script>
1.2. BOM
1.2.1. 什么是BOM
? BOM(Browser Object Model)即瀏覽器對象模型疙挺,它提供了獨立于內(nèi)容而與瀏覽器窗口進行交互的對象扛邑,其核心對象是 window。
? BOM 由一系列相關(guān)的對象構(gòu)成铐然,并且每個對象都提供了很多方法與屬性蔬崩。
? BOM 缺乏標準恶座,JavaScript 語法的標準化組織是 ECMA,DOM 的標準化組織是 W3C舱殿,BOM 最初是Netscape 瀏覽器標準的一部分奥裸。
1.2.2. BOM的構(gòu)成
BOM 比 DOM 更大险掀,它包含 DOM沪袭。
1.2.3. 頂級對象window
1.2.4. window對象的常見事件
頁面(窗口)加載事件(2種)
第1種
window.onload 是窗口 (頁面)加載事件,當文檔內(nèi)容完全加載完成會觸發(fā)該事件(包括圖像樟氢、腳本文件冈绊、CSS 文件等), 就調(diào)用的處理函數(shù)。
第2種
? DOMContentLoaded 事件觸發(fā)時埠啃,僅當DOM加載完成死宣,不包括樣式表,圖片碴开,flash等等毅该。
? IE9以上才支持!A逝!眶掌!
? 如果頁面的圖片很多的話, 從用戶訪問到onload觸發(fā)可能需要較長的時間, 交互效果就不能實現(xiàn),必然影響用戶的體驗巴碗,此時用 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>
調(diào)整窗口大小事件
? window.onresize 是調(diào)整窗口大小加載事件, 當觸發(fā)時就調(diào)用的處理函數(shù)。
注意:
只要窗口大小發(fā)生像素變化橡淆,就會觸發(fā)這個事件召噩。
我們經(jīng)常利用這個事件完成響應(yīng)式布局。 window.innerWidth 當前屏幕的寬度
<script>
// 注冊頁面加載事件
window.addEventListener('load', function() {
var div = document.querySelector('div');
// 注冊調(diào)整窗口大小事件
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() 炸彈定時器
開啟定時器
普通函數(shù)是按照代碼順序直接調(diào)用具滴。 簡單理解: 回調(diào),就是回頭調(diào)用的意思师倔。上一件事干完抵蚊,再回頭再調(diào)用這個函數(shù)。 例如:定時器中的調(diào)用函數(shù)溯革,事件處理函數(shù)贞绳,也是回調(diào)函數(shù)。 以前我們講的 element.onclick = function(){} 或者 element.addEventListener(“click”, fn); 里面的 函數(shù)也是回調(diào)函數(shù)致稀。
<script>
// 回調(diào)函數(shù)是一個匿名函數(shù)
setTimeout(function() {
console.log('時間到了');
}, 2000);
function callback() {
console.log('爆炸了');
}
// 回調(diào)函數(shù)是一個有名函數(shù)
var timer1 = setTimeout(callback, 3000);
var timer2 = setTimeout(callback, 5000);
</script>
案例:5秒后關(guān)閉廣告
<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('繼續(xù)輸出');
}, 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'); // 秒數(shù)的黑色盒子
var inputTime = +new Date('2019-5-1 18:00:00'); // 返回的是用戶輸入時間總的毫秒數(shù)
countDown(); // 我們先調(diào)用一次這個函數(shù)冈闭,防止第一次刷新頁面有空白
// 2. 開啟定時器
setInterval(countDown, 1000);
function countDown() {
var nowTime = +new Date(); // 返回的是當前時間總的毫秒數(shù)
var times = (inputTime - nowTime) / 1000; // times是剩余時間總的秒數(shù)
var h = parseInt(times / 60 / 60 % 24); //時
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>
停止定時器
案例:發(fā)送短信倒計時
? 點擊按鈕后,該按鈕60秒之內(nèi)不能再次點擊抖单,防止重復(fù)發(fā)送短信萎攒。
手機號碼: <input type="number"> <button>發(fā)送</button>
<script>
var btn = document.querySelector('button');
// 全局變量遇八,定義剩下的秒數(shù)
var time = 3;
// 注冊單擊事件
btn.addEventListener('click', function() {
// 禁用按鈕
btn.disabled = true;
// 開啟定時器
var timer = setInterval(function() {
// 判斷剩余秒數(shù)
if (time == 0) {
// 清除定時器和復(fù)原按鈕
clearInterval(timer);
btn.disabled = false;
btn.innerHTML = '發(fā)送';
} else {
btn.innerHTML = '還剩下' + time + '秒';
time--;
}
}, 1000);
});
</script>
1.2.6. this指向問題
? this的指向在函數(shù)定義的時候是確定不了的,只有函數(shù)執(zhí)行的時候才能確定this到底指向誰耍休,一般情況下this的最終指向的是那個調(diào)用它的對象刃永。
現(xiàn)階段,我們先了解一下幾個this指向
全局作用域或者普通函數(shù)中this指向全局對象window(注意定時器里面的this指向window)
方法調(diào)用中誰調(diào)用this指向誰
構(gòu)造函數(shù)中this指向構(gòu)造函數(shù)的實例
<button>點擊</button>
<script>
// this 指向問題 一般情況下this的最終指向的是那個調(diào)用它的對象
// 1. 全局作用域或者普通函數(shù)中this指向全局對象window( 注意定時器里面的this指向window)
console.log(this);
function fn() {
console.log(this);
}
window.fn();
window.setTimeout(function() {
console.log(this);
}, 1000);
// 2. 方法調(diào)用中誰調(diào)用this指向誰
var o = {
sayHi: function() {
console.log(this); // this指向的是 o 這個對象
}
}
o.sayHi();
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
console.log(this); // 事件處理函數(shù)中的this指向的是btn這個按鈕對象
})
// 3. 構(gòu)造函數(shù)中this指向構(gòu)造函數(shù)的實例
function Fun() {
console.log(this); // this 指向的是fun 實例對象
}
var fun = new Fun();
</script>
1.2.7. location對象
什么是 location 對象
location 對象的屬性
案例:5分鐘自動跳轉(zhuǎn)頁面
<button>點擊</button>
<div></div>
<script>
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.addEventListener('click', function() {
// console.log(location.href);
location.;
})
var timer = 5;
setInterval(function() {
if (timer == 0) {
location.;
} else {
div.innerHTML = '您將在' + timer + '秒鐘之后跳轉(zhuǎn)到首頁';
timer--;
}
}, 1000);
</script>
案例:獲取URL參數(shù)
<div></div>
<script>
console.log(location.search); // ?uname=andy
// 1.先去掉羊精? substr('起始的位置'斯够,截取幾個字符);
var params = location.search.substr(1); // uname=andy
console.log(params);
// 2. 利用=把字符串分割為數(shù)組 split('=');
var arr = params.split('=');
console.log(arr); // ["uname", "ANDY"]
var div = document.querySelector('div');
// 3.把數(shù)據(jù)寫入div中
div.innerHTML = arr[1] + '歡迎您';
</script>
location對象的常見方法
<button>點擊</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
// 記錄瀏覽歷史,所以可以實現(xiàn)后退功能
// location.assign('http://www.itcast.cn');
// 不記錄瀏覽歷史喧锦,所以不可以實現(xiàn)后退功能
// location.replace('http://www.itcast.cn');
location.reload(true);
})
</script>
1.2.8. navigator對象
? navigator 對象包含有關(guān)瀏覽器的信息读规,它有很多屬性,我們最常用的是 userAgent燃少,該屬性可以返回由客戶機發(fā)送服務(wù)器的 user-agent 頭部的值束亏。
下面前端代碼可以判斷用戶那個終端打開頁面,實現(xiàn)跳轉(zhuǎn)
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對象一般在實際開發(fā)中比較少用阳液,但是會在一些 OA 辦公系統(tǒng)中見到怕敬。
1.3. JS執(zhí)行機制
以下代碼執(zhí)行的結(jié)果是什么?
console.log(1);
setTimeout(function () {
console.log(3);
}, 1000);
console.log(2);
以下代碼執(zhí)行的結(jié)果是什么趁舀?
console.log(1);
setTimeout(function () {
console.log(3);
}, 0);
console.log(2);
1.3.1 JS 是單線程
單線程就意味著赖捌,所有任務(wù)需要排隊,前一個任務(wù)結(jié)束矮烹,才會執(zhí)行后一個任務(wù)越庇。如果前一個任務(wù)耗時很長,后一個任務(wù)就不得不一直等著奉狈。
這樣所導(dǎo)致的問題是: 如果 JS 執(zhí)行的時間過長卤唉,這樣就會造成頁面的渲染不連貫,導(dǎo)致頁面渲染加載阻塞的感覺仁期。
1.3.2 同步任務(wù)和異步任務(wù)
? 單線程導(dǎo)致的問題就是后面的任務(wù)等待前面任務(wù)完成桑驱,如果前面任務(wù)很耗時(比如讀取網(wǎng)絡(luò)數(shù)據(jù)),后面任務(wù)不得不一直等待u说啊熬的!
? 為了解決這個問題,利用多核 CPU 的計算能力赊级,HTML5 提出 Web Worker 標準押框,允許 JavaScript 腳本創(chuàng)建多個線程,但是子線程完全受主線程控制理逊。于是橡伞,JS 中出現(xiàn)了同步任務(wù)和異步任務(wù)盒揉。
同步
? 前一個任務(wù)結(jié)束后再執(zhí)行后一個任務(wù),程序的執(zhí)行順序與任務(wù)的排列順序是一致的兑徘、同步的刚盈。比如做飯的同步做法:我們要燒水煮飯,等水開了(10分鐘之后)挂脑,再去切菜藕漱,炒菜。
異步
? 你在做一件事情時最域,因為這件事情會花費很長時間谴分,在做這件事的同時锈麸,你還可以去處理其他事情镀脂。比如做飯的異步做法,我們在燒水的同時忘伞,利用這10分鐘薄翅,去切菜,炒菜氓奈。
JS中所有任務(wù)可以分成兩種翘魄,一種是同步任務(wù)(synchronous),另一種是異步任務(wù)(asynchronous)舀奶。 同步任務(wù)指的是: 在主線程上排隊執(zhí)行的任務(wù)暑竟,只有前一個任務(wù)執(zhí)行完畢,才能執(zhí)行后一個任務(wù)育勺; 異步任務(wù)指的是: 不進入主線程但荤、而進入”任務(wù)隊列”的任務(wù),當主線程中的任務(wù)運行完了涧至,才會從”任務(wù)隊列”取出異步任務(wù)放入主線程執(zhí)行腹躁。
1.3.3 JS執(zhí)行機制(事件循環(huán))
1.3.4 代碼思考題
console.log(1);
document.onclick = function() {
console.log('click');
}
setTimeout(function() {
console.log(3)
}, 3000)
console.log(2);