指使计算机能随时发现事件的发生
设置事件监听
DOM0级事件监听-只能监听冒泡
oBox. onxxx=function(){
};
DOM2级事件监听-捕获&冒泡皆可监听
// 事件名click不加on
oBox.addEventListener('click', function () {
}, true);
其中,true监听捕获阶段;false监听冒泡阶段
IE6~8 不支持 addEventListener
事件监听类型
鼠标事件监听
事件名 | 事件描述 |
---|---|
onclick | 当鼠标单击某个对象 |
ondblclick | 当鼠标双击某个对象 |
onmousedown | 当某个鼠标按键在某个对象上被按下 |
onmouseup | 当某个鼠标按键在某个对象上被松开 |
onmousemove | 当某个鼠标按键在某个对象上被移动 |
onmouseenter | 当鼠标进入某个对象(相似事件onmouseover) |
onmouseleave | 当鼠标离开某个对象(相似事件onmouseout) |
<style>
.box {
width: 200px;
height: 200px;
background-color: red;
}
</style>
<body>
<div class='box' id="box"></div>
<script>
var oBox = document.getElementById('box');
oBox.onclick = function () {
alert('你好,我是点击事件函数');
}
</script>
</body>
键盘事件监听
事件名 | 事件描述 |
---|---|
onkeypress | 当某个键盘的键被按下(系统按钮如箭头键和功能键无法得到识别) |
onkeydown | 当某个键盘的键被按下(系统按钮可以识别,并且会先于onkeypress发生) |
onkeyup | 当某个键盘的键被松开 |
案例- 按键移动盒子
<div id="box"></div>
<script>
var oBox = document.getElementById('box');
// t表示盒子的top属性值
// l表示盒子的left属性值
var t = 200;
var l = 200;
document.onkeydown = function (e) {
switch (e.keyCode) {
case 37:
l -= 3;
break;
case 38:
t -= 3;
break;
case 39:
l += 3;
break;
case 40:
t += 3;
break;
}
oBox.style.top = t + 'px';
oBox.style.left = l + 'px';
}
</script>
表单事件监听
事件名 | 事件描述 |
---|---|
onchange | 当用户改变域的内容 |
onfocus | 当某元素获得焦点(比如tab键或鼠标点击) |
onblur | 当某元素失去焦点 |
onsubmit | 当表单被提交 |
onreset | 当表单被重置 |
<body>
<form id='myform' action="">
<p>
姓名:
<input type="text" name="nameField">
</p>
<p>
年龄:
<input type="text" name="ageField">
</p>
<p>
<input type="submit">
</p>
</form>
<script>
var myform = document.getElementById('myform');
// 表单的name属性打点调用
var nameField = myform.nameField;
var ageField = myform.ageField;
nameField.onchange = function () {
console.log('您修改了姓名');
}
nameField.oninput = function () {
console.log('您正在修改姓名');
}
nameField.onfocus = function () {
console.log('姓名框已得到焦点');
}
nameField.onblur = function () {
console.log('姓名框已失去焦点');
}
myform.onsubmit = function () {
console.log("您正在提交表单");
}
</script>
</body>
页面事件监听
事件名 | 事件描述 |
---|---|
onload | 当页面或图像被完成加载 |
onunload | 当用户退出页面 |
*更多有关窗口或页面的事件在BOM课程中介绍 |
事件传播(先从外到内,再从内到外)
观察
<style>
#box1 {
width: 202px;
height: 202px;
border: 1px solid black;
padding: 50px;
}
#box2 {
width: 100px;
height: 100px;
border: 1px solid black;
padding: 50px;
}
#box3 {
width: 100px;
height: 100px;
border: 1px solid black;
}
</style>
<body>
<div id="box1">
<div id="box2">
<div id="box3"></div>
</div>
</div>
<script>
var oBox1 = document.getElementById("box1");
var oBox2 = document.getElementById("box2");
var oBox3 = document.getElementById("box3");
// 打乱监听事件函数顺序,结果依然如此
//事件传播从内到外,与监听事件函数顺序无关
oBox2.onclick = function () {
console.log("我是box2的onclick");
};
oBox3.onclick = function () {
console.log("我是box3的onclick");
};
oBox1.onclick = function () {
console.log("我是box1的onclick");
};
</script>
</body>
观察结果:从内到外;不确切,因为DOM0级事件只能监听冒泡阶段
实际结论:先从外到内,然后再从内到外
最内部元素不区分捕获和冒泡阶段
执行结果:
oBox1.addEventListener(
"click",
function () {
console.log("我是box1的捕获阶段");
},
true
);
oBox2.addEventListener(
"click",
function () {
console.log("我是box2的捕获阶段");
},
true
);
oBox3.addEventListener(
"click",
function () {
console.log("我是box3的捕获阶段");
},
true
);
oBox1.addEventListener(
"click",
function () {
console.log("我是box1的冒泡阶段");
},
false
);
oBox2.addEventListener(
"click",
function () {
console.log("我是box2的冒泡阶段");
},
false
);
oBox3.addEventListener(
"click",
function () {
console.log("我是box3的冒泡阶段");
},
false
);
同名事件互相覆盖问题
若给元素设置相同的两个或多个同名事件,
DOM0级写法后面写的会覆盖先写的;
而DOM2级会按顺序执行
事件对象
事件处理函数提供一个形式参数,它是一个对象,封装了本次事件的细节
这个参数通常用单词event或字母e来表示
oBox.onmousemove = function (e) {
//对象e就是这次事件的“事件对象”
};
鼠标位置
属性 | 属性描述 |
---|---|
clientX | 鼠标指针相对于浏览器的水平坐标 |
clientY | 鼠标指针相对于浏览器的垂直坐标 |
pagex | 鼠标指针相对于整张网页的水平坐标 |
pageY | 鼠标指针相对于整张网页的垂直坐标 |
offsetX | 鼠标指针相对于事件源元素的水平坐标 |
offsetY | 鼠标指针相对于事件源元素的垂直坐标 |
e.charCode
表示用户输入字符的“字符码”
通常用于onkeypress事件中
字符 | 字符码 |
---|---|
0~9 | 48~57 |
A~Z | 65~90 |
a~z | 97~122 |
e.keyCode
表示用户按下按键的“键码”
通常用于onkeydown事件和onkeyup中
按键 | 键码 |
---|---|
0~9 | 48~57 |
a~z(不分大小写) | 65~90 |
方向键(左、上、右、下) | 37、38、39、40 |
回车键 | 13 |
空格键 | 32 |
<body>
<input id='field1' type="text">
<h1 id='info1'></h1>
<input id='field2' type="text">
<h1 id='info2'></h1>
<script>
var oField1 = document.getElementById('field1');
var oInfo1 = document.getElementById('info1');
var oField2 = document.getElementById('field2');
var oInfo2 = document.getElementById('info2');
oField1.onkeypress = function (e) {
oInfo1.innerText = '您输入的字符的字符码是' + e.charCode;
}
oField2.onkeydown = function (e) {
oInfo2.innerText = '您按下的按键的键码是' + e.keyCode;
}
</script>
</body>
e.preventDefault()-阻止默认动作
1)DOM2级
e.preventDefault()
2)DOM0级
最后加:return false;
例:阻止表单默认动作
Form.onsubmit = function () {
return false;
}; //可阻止默认提交动作
案例-当标在盒子中向下滚动,数字加1;反之,数字减1
onmousewheel鼠标滚轮事件
deltaY属性表示鼠标滚动方向,向下滚动时返回正值,向上滚动时返回负值
<div id="box"></div>
<h1 id="info">0</h1>
<script>
var oBox = document.getElementById("box");
var oInfo = document.getElementById("info");
var a = 0;
oBox.onmousewheel = function (e) {
/* 页面较长时,使用阻止默认事件
即用户在盒子内部滚动鼠标滚轮时,不会引发页面滚动条的滚动 */
e.preventDefault();
if (e.deltaY > 0) {
a--;
} else {
a++;
}
oInfo.innerText = a;
};
</script>
e.stopPropagation()-阻止继续传播
在一些场合,非常有必要切断事件继续传播,否则会造成页面特效显示出bug
案例
<style>
#box {
width: 200px;
height: 200px;
background-color: red;
}
</style>
<body>
<div id="box">
<button id="btn">按我</button>
</div>
<script>
var oBox = document.getElementById("box");
var oBtn = document.getElementById("btn");
// oBox.onclick = function () {
// console.log("我是盒子");
// };
// oBtn.onclick = function (e) {
// //阻止冒泡-点击btn只打印我是按钮
// e.stopPropagation();
// console.log("我是按钮");
// };
oBox.addEventListener(
"click",
function (e) {
// 阻止捕获-点击btn只打印我是盒子
e.stopPropagation();
console.log("我是盒子");
},
true
);
oBtn.addEventListener(
"click",
function () {
console.log("我是按钮");
},
true
);
</script>
</body>
事件委托
性能问题
作用1-批量添加事件监听
每一个事件监听注册都会消耗一定的系统内存,而批量添加事件监听数量太多,导致内存消耗更大
例如:每个<1i>的事件处理函数都是不同的函数,占用更多内存
<ul id="list">
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
<li>列表项</li>
</ul>
<script>
var oList = document.getElementById("list");
var lis = oList.getElementsByTagName("li");
// 循环语句,给元素批量添加监听
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
//this指代点击的元素
this.style.color = "red";
};
}
</script>
作用2-实现自动绑定事件
新增元素不能自动获得事件监听
原理:利用事件冒泡机制,将后代元素事件委托给祖先元素
e.target-事件源元素
触发此事件的最早元素,即“事件源元素”
e.currentTarget-事件处理程序附加到的元素
使用场景
1)需要批量添加事件监听时
2)当有动态元素节点上树时
例1:点击任一个li元素,事件都会通过冒泡传递给祖先元素
<body>
<button id="btn">按我添加新的li列表项</button>
<ul id="list">
<li>默认项</li>
<li>默认项</li>
<li>默认项</li>
</ul>
<script>
var oBtn = document.getElementById("btn");
var oList = document.getElementById("list");
oList.onclick = function (e) {
// e.target表示用户真正点击的那个元素
e.target.style.color = "red";
};
oBtn.onclick = function () {
var oLi = document.createElement("li");
oLi.innerText = "我是新来的";
oList.appendChild(oLi);
};
</script>
</body>
例2:
<button id="btn">按我添加新的li列表项</button>
<ul id="list">
<li>默认项</li>
<li>默认项</li>
<li>默认项</li>
</ul>
<script>
var oList = document.getElementById("list");
var oBtn = document.getElementById("btn");
// onmouseenter不冒泡
//相当于事件处理函数直接附加给了DOM节点
oList.onmouseenter = function (e) {
// e.target表示用户真正点击的那个元素
e.target.style.color = "red";
};
oBtn.onclick = function () {
// 创建新的li元素
var oLi = document.createElement("li");
// 写内容
oLi.innerText = "我是新来的";
// 上树
oList.appendChild(oLi);
};
</script>
onmouseenter&onmouseover
都表示“鼠标进入"
区别:onmouseenter不冒泡,onmouseover冒泡。