基本概念
- 事件是一些特定動作發生時所發出的信號,JavaScript中的事件是可以被 JavaScript 偵測到的行為。
- 網頁中的每個元素都可以產生某些事件。比方說,我們可以在用戶點擊某按鈕時產生一個 onClick 事件來觸發某個函數。
事件處理(添加事件)
- (HTML事件處理)內聯方式添加事件將事件看做標簽的一個屬性,與HTML混寫,代碼多時不容易管理
(DOM0級事件處理)腳本方式添加事件,實現了HTML和JS的分離
-
DOM2級事件處理
- ele.addEventListener()
- ele.removeEventListener()
- IE8及其以下需要使用IE事件處理程序attachEvent/detachEvent
var div1 = document.getElementById('div1'); var btn2 = document.getElementById('btn2'); var btn3 = document.getElementById('btn3'); function test1() { div1.innerHTML='點擊事件'; } function test2() { div1.style.background = 'rgb(52, 205, 112)'; } // DOM 0級事件處理 btn2.onclick = test2;// 不用謝() // DOM 2級事件處理 if (btn3.addEventListener) { btn3.addEventListener('click',test1); btn3.addEventListener('click',test2); btn3.removeEventListener('click',test2); }else if (btn3.attachEvent) { btn3.attachEvent('click',test1); btn3.attachEvent('click',test2); btn3.detachEvent('click',test2); }
常用的事件類型(事件處理函數)
鼠標事件
- onclick 鼠標點擊某個對象
- ondblclick 當用戶雙擊某個對象時調用的事件句柄。
ondblclick="test1()"
- onmousedown 鼠標按鈕被按下。
onmousedown="test1()"
- onmousemove 鼠標被移動。
onmousemove="test1()"
- onmouseout 鼠標從某元素移開。
onmouseout="test1()"
- onmouseover 鼠標移到某元素之上。
addEventListener('mouseover',test1())
- onmouseup 鼠標按鍵被松開。
onmouseup="test1()"
- ......
btn3.detachEvent('click',
// 匿名函數
function () {
xxx
}
);
鍵盤事件
- onkeydown 某個鍵盤按鍵被按下。
- onkeyup 某個鍵盤按鍵被松開。
- onkeypress 某個鍵盤按鍵被按下并松開。
- onkeydown與onkeypress的區別
- 一個放開一個沒有放開,onkeydown 先于 onkeypress 發生。
- 我們沒敲擊一下鍵盤這三個事件會依次發生:onkeydown--onkeypress--onkeyup
- onkeypress 事件不是適用于系統按鈕(如: ALT, CTRL, SHIFT, ESC)。
- onkeydown 是在用戶按下任何鍵盤鍵時發生。 監聽一個用戶是否按下按鍵請使用 onkeydown 事件,所有瀏覽器都支持 onkeydown 事件。
- 鍵盤事件的event對象中包含一個keyCode屬性,onkeydown和onkeyup表示你按下的具體的鍵,而onkeypress表示你按下的字符。
- ......
onkeydown="test1()"
body中添加
其他事件
- onload 一個頁面或一幅圖像完成加載
- onunload 用戶退出頁面。
- IE6,IE7,IE8 中 刷新頁面、關閉瀏覽器之后、頁面跳轉之后都會執行.
- IE9 刷新頁面 會執行,頁面跳轉、關閉瀏覽器不能執行;
- Opera、Chrome 任何情況都不執行。
- onabort 圖像的加載被中斷
- onblur 元素失去焦點。
- onchange 域的內容被改變。
- onerror 在加載文檔或圖像時發生錯誤。
- onfocus 元素獲得焦點。
- onselect 文本被選中。
- onreset 重置按鈕被點擊。
- onscroll 當文檔被滾動時發生的事件。
- ......
或者放到body
// window.onload=function (){
// myFun4()
// }
事件的對象
在觸發某個事件時,會產生一個事件對象event。這個對象中包含著所有與事件有關的信息。包括導致事件的元素,事件的類型以及其他與特定事件相關的信息。
- type:獲取事件類型
- target:獲取事件目標
- clientX 返回當事件被觸發時,鼠標指針的水平坐標。
- clientY 返回當事件被觸發時,鼠標指針的垂直坐標。
- screenX 返回當某個事件被觸發時,鼠標指針的水平坐標。
- screenY 返回當某個事件被觸發時,鼠標指針的垂直坐標。
- ctrlKey 返回當事件被觸發時,"CTRL" 鍵是否被按下。
- altKey 返回當事件被觸發時,"ALT" 是否被按下。
- shiftKey 返回當事件被觸發時,"SHIFT" 鍵是否被按下。
- keyCode 事件屬性 keyCode 屬性在 Firefox 瀏覽器的 onkeypress 事件中是無效的。
- which 返回onkeypress事件觸發的鍵的值的字符代碼,或者 onkeydown 或 onkeyup 事件的鍵的代碼。
注意:IE8 及其更早版本不支持 which 屬性。不支持的瀏覽器可使用 keyCode 屬性。但是, keyCode 屬性在 Firefox 瀏覽器的 onkeypress 事件中是無效的。 var x = event.which || event.keyCode; // 使用 which 或 keyCode, 這樣可支持不同瀏覽器
- button 返回當事件被觸發時,哪個鼠標按鈕被點擊。
- button 事件屬性可返回一個整數,指示當事件被觸發時哪個鼠標按鍵被點擊。event.button=0|1|2
- 0 1 2分別代表左中右三個鍵,但是再IE里左中右三個鍵對應的數字為1 4 2
- ......
事件的冒泡和捕獲
- 事件的冒泡:事件按照從最特定的事件目標到最不特定的事件目標的順序觸發。
- 事件冒泡可以形象地比喻為把一顆石頭投入水中,泡泡會一直從水底冒出水面。也就是說,事件會從最內層的元素開始發生,一直向上傳播,直到document對象。
- 事件的捕獲:與事件冒泡相反,事件會從最外層開始發生,直到最具體的元素。
- 事件捕獲時,父級元素先觸發,子級元素后觸發
- 可以自己選擇綁定事件時采用事件捕獲還是事件冒泡,方法就是綁定事件時通過addEventListener函數,它有三個參數,第三個參數若是true,則表示采用事件捕獲,若是false,則表示采用事件冒泡。
- IE9以前的版本只支持事件冒泡,不支持事件捕獲,它也不支持addEventListener函數,不會用第三個參數來表示是冒泡還是捕獲,它提供了另一個函數attachEvent。
- 不是所有的事件都能冒泡,例如:blur、focus、load、unload
- stopPropagation():阻止事件冒泡
- preventDefault():阻止事件的默認行為
事件的綁定
- ele.addEventListener()
- ele.removeEventListener()
// 循環變化顏色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style type="text/css">
#div1{
margin: 15px auto;
background: orange;
width: 200px;
height: 200px;
border-radius: 200px;
}
</style>
</head>
<body>
<div id="div1"></div>
<script type="text/javascript">
var div1 = document.getElementById('div1');
div1.onclick=test1;
function test1() {
div1.style.background = 'rgb(41, 48, 173)';
setTimeout('test2()',500);
}
function test2() {
div1.style.background = 'rgb(173, 65, 41)';
setTimeout('test3()',500);
}
function test3() {
div1.style.background = 'rgb(43, 173, 41)';
setTimeout('test1()',500);
}
</script>
</body>
</html>
- scrollLeft:設置或獲取位于對象左邊界和窗口中目前可見內容的最左端之間的距離
- scrollTop:設置或獲取位于對象最頂端和窗口中可見內容的最頂端之間的距離
- scrollHeight: 獲取對象的滾動高度。
- scrollWidth:獲取對象的滾動寬度
- document.documentElement.scrollTop||document.body.scrollTop 垂直方向滾動的值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style type="text/css">
div{
margin: 15px auto;
background: orange;
width: 200px;
height: 200px;
padding: 15px;
border-radius: 200px;
position: absolute;
}
</style>
</head>
<body>
<script type="text/javascript">
function test1(e) {
var num = 20;
var divs = document.getElementsByTagName('div');
var body = document.getElementsByTagName('body')[0];
for (var i = 0; i < num; i++) {
var rad = Math.floor(Math.random()*10)+'px';
divs[i] = document.createElement('div');
divs[i].style.background='rgb('+4*i+','+2*i+','+i+')';
divs[i].style.width=divs[i].style.height=rad
divs[0].style.left=e.clientX+'px';
divs[0].style.top=e.clientY+'px';
divs[i].style.left=e.clientX+Math.floor(Math.random()*10*i)+'px';
divs[i].style.top=e.clientY+Math.floor(Math.random()*10*i)+'px';
body.appendChild(divs[i])
}
}
document.onmousedown=test1;
</script>
</body>
</html>
// 隨機鍵盤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style type="text/css">
input{
width: 30px;
height: 30px;
border-radius: 20px;
margin: 2px;
outline: none;
}
.div{
width: 120px;
height: 150px;
padding: 10px;
text-align: center;
background: rgba(180,90,30,0.3);
border:2px solid orange;
}
.inp{
width: 130px;
height: 20px;
}
.clear,.new{
width: 60px;
font-size: 12px;
}
</style>
</head>
<body>
<input type="text" class="inp" id="txt"><br>
<input type="button" class="clear" value="清楚" onclick="clearnum()">
<input type="button" class="new" value="重置鍵盤" onclick="cz()">
<div id="div1" class="div"></div>
<script type="text/javascript">
var txt = document.getElementById('txt');
var div1 = document.getElementById('div1');
// 生成隨機數
function number() {
var num = [0,1,2,3,4,5,6,7,8,9];
var rand = [];
for (var i = 0; i < 10; i++) {
var n = Math.floor(Math.random()*(10-i));
rand.push(num[n]);
num.splice(n,1)// 刪除num數組中下標為n的元素,保證不會出現重復數字
}
return rand;
}
document.write(number())
function createBtn() {
var ranArr = number();
var btnArr = [];
for (var i = 0; i < ranArr.length; i++) {
var btn = document.createElement('input');
btn.setAttribute('type','button');
btn.value = ranArr[i];
btn.onclick = btnClick;
btnArr.push(btn);
div1.appendChild(btn);
}
}
createBtn();
function btnClick() {
txt.value += this.value;// 這里this就是調用這個函數的對象
}
function clearnum() {
txt.value = '';
}
function cz() {
window.location.reload();
}
</script>
</body>
</html>
HTML5新增的JS選擇器
在傳統的 JavaScript 開發中,原生的 JavaScript 所提供的 DOM 選擇方法并不多,僅僅局限于通過 tag, name, id 等方式來查找,這顯然是遠遠不夠的,如果想要進行更為精確的選擇不得不使用看起來非常繁瑣的正則表達式,或者使用某個庫。
querySelector 和 querySelectorAll 方法是 W3C Selectors API 規范中定義的。他們的作用是根據 CSS 選擇器規范,便捷定位文檔中指定元素。 現在所有的瀏覽器廠商都提供了 querySelector 和 querySelectorAll 這兩個方法的支持,使用它們,你可以像使用 CSS 選擇器一樣快速地查找到你需要的節點。
HTML5新增的JS選擇器
querySelector 和 querySelectorAll 方法是 W3C Selectors API 規范中定義的。他們的作用是根據 CSS 選擇器規范,便捷定位文檔中指定元素。功能類似于jQuery的選擇器。這使得在編寫原生JavaScript代碼時方便了許多。
- document.querySelector('selectors');
- 該方法返回滿足條件的單個元素。按照深度優先和先序遍歷的原則使用參數提供的CSS選擇器在DOM進行查找,返回第一個滿足條件的元素
-
document.querySelectorAll('selectors');
- 該方法返回所有滿足條件的元素,結果是個nodeList集合。查找規則與前面所述一樣。
-
注意事項
- 參數selectors 可以包含多個CSS選擇器,用逗號隔開:element = document.querySelector('selector1,selector2,...');br>elementList = document.querySelectorAll('selector1,selector2,...');
- 這種方法查找元素是非實時的,即不支持有動態添加元素情況下的查找
-
document.getElementsByClassName("selector");返回文檔中所有指定類名的元素集合,作為 NodeList 對象。
- IE8以下的瀏覽器中,無法通過Class標簽getElementsByClassName函數獲取元素。ie9以上及主流瀏覽器均支持通過Class獲取元素,ie8及以下的解決辦法:
- 可以用jQuery代替 引用jQuery后,使用$(".ClassName")等方法獲取元素。
- 自己寫getElementsByClassName函數方法
<script> //快捷的通過class ID 元素名稱查找元素 function myFun1(){ // document.querySelector("li").style.backgroundColor = "red"; // document.querySelector("#u2").style.backgroundColor = "blue"; document.querySelector(".bb").style.backgroundColor = "blue"; } //結合CSS3的選擇器進行更精確的查找 function myFun2(){ document.querySelector("#u2>li+li").style.backgroundColor = "red"; document.querySelector("#u1 li p").style.backgroundColor = "red"; } //只匹配第一個符合條件的元素 function myFun3(){ document.querySelector("h2, h3").style.backgroundColor = "red"; } //querySelectorAll返回的是一個集合 function myFun4() { var x=document.querySelectorAll("li"); x[3].style.backgroundColor = "green" //alert(x.length) for (var i = 0; i < x.length; i++) { x[i].style.backgroundColor = "red"; } } function myFun5(){ var x=document.querySelectorAll("#u1 .bb") for (var i = 0; i < x.length; i++) { x[i].style.backgroundColor = "green"; } } //querySelectorAll查找元素不是實時的 function myFun6(){ var u1=document.getElementById('u1') // var arr=document.querySelectorAll("#u1>li") var arr=u1.getElementsByTagName('li') alert(arr.length) var newli=document.createElement('li') newli.innerHTML='newli' u1.appendChild(newli) alert(arr.length) } //通過className查找元素 function myFun7() { var x = document.getElementsByClassName("bb"); for (var i = 0; i < x.length; i++) { x[i].style.backgroundColor = "red"; } } </script>
瀏覽器兼容性
- 版本較低的瀏覽器有會存在兼容性問題。
- 很多框架中封裝了解決瀏覽器兼容性的問題的方法,比如JQ;使用合適的框架不但可以解決兼容性還可以節省很多時間,效率更高
- 在不用框架的情況下可以自己編寫一個解決兼容性的函數,或者直接引用一個解決兼容問題的函數
- 相信隨著瀏覽器的更新和語言的規范這些目前的兼容性問題未來很可能就不存在了
理解全局對象Global
- 全局屬性和函數可用于所有內建的 JavaScript 對象。全局對象是所有全局方法的擁有者,用來統一管理全局方法,全局方法也就是全局函數。
- parseInt() 函數可解析一個字符串,并返回一個整數。
- parseFloat() 解析一個字符串并返回一個浮點數。
- 注意:可以將數字開頭的字符串轉換成數值,但是不可以轉換非數字開頭的字符串
- 如果指定的字符串中包含非數字字符,只要字符串開頭的一部分符合整數的轉換規則,則parseInt()函數會將這一部分字符串轉化為整數(從字符串開頭,直到遇到非數字字符為止)。如果字符串以非數字字符開頭,則返回NaN。
- isNaN(x)函數用于檢查其參數是否是非數字值。NaN 即 Not a Number
- 可用于判斷其參數是否是 NaN,該值表示一個非法的數字
- 如果 x 是特殊的非數字值 NaN(或者能被轉換為這樣的值),返回的值就是 true。如果 x 是其他值,則返回 false。
- isNaN() 函數通常用于檢測 parseFloat() 和 parseInt() 的結果,以判斷它們表示的是否是合法的數字。當然也可以用 isNaN() 函數來檢測算數錯誤,比如用 0 作除數的情況。
- ......
變量的作用范圍
- 作用域是指有效范圍,JS變量的作用域有全局和局部之分
- "全局變量":申明在函數之外的變量
- "局部變量":申明在函數體中的變量,并且只能在當前函數體內訪問
- 如果函數內部有定義變量,即使在定義之前輸出但會先執行后面定義語句,然后判斷輸出結果
- 全局變量的優點:可以減少變量的個數,減少由于實際參數和形式參數的數據傳遞帶來的時間消耗。
- 全局變量缺點:使函數的代碼可讀性降低。由于多個函數都可能使用全局變量,函數執行時全局變量的值可能隨時發生變化,對于程序的查錯和調試都非常不利。