JavaScript中有许多DOM事件
添加事件的方法
- 通过onXXX的方式来添加
//1.使用onXXX添加事件
oBtn.onclick = function () {
alert("11");
};
//同一个元素添加相同的事件后添加的会覆盖前面添加的事件
oBtn.onclick = function () {
alert("22");
};
注意点: 由于是添加给了属性, 所以后赋值的会覆盖先赋值
- 通过addEventListener方法添加(IE9以上)
//2.使用addEventListener添加事件
oBtn.addEventListener("click",function () {
alert("11");
});
//后添加的不会覆盖先添加的
oBtn.addEventListener("click",function () {
alert("22");
})
注意点:
1.事件名称不需要添加on
2.后添加的不会覆盖先添加的
3.只支持最新的浏览器IE9
- 通过attachEvent方法添加(低版本浏览器)
//attachEvent只支持低版本浏览器
//兼容性处理
function addEvent(ele,name,fn) {
//兼容低版本浏览器
if (ele.attachEvent) {
ele.attachEvent("on"+ name,fn);
}else {
ele.addEventListener(name,fn);
}
}
注意点:
1.事件名称必须加上on
2.后添加的不会覆盖先添加的
3.只支持低版本的浏览器
点击事件
- 格式:元素.onclick = function(){};
当调用者被点击的时候, 就会执行后面赋值的这个函数
oDiv.onclick = function () {
alert("haha");
}
注意点:
如果是给a标签添加点击事件, 由于a标签对点击事件有默认的实现(跳转)
所以需要注意的是我们添加的点击事件不会覆盖掉系统默认的点击事件
如果不想使用系统的默认事件, 那么只需要在我们添加的函数中return false
即可
var oA = document.querySelector("a");
oA.onclick = function () {
alert("hehe");
return false;
}
移入移出事件
- 鼠标移入事件
onmouseover作用: 监听鼠标移入元素
onmouseenter作用: 监听鼠标移入元素 - 鼠标移出事件
onmousout作用: 监听鼠标移出元素
onmousleave作用: 监听鼠标移出元素
注意点:
添加鼠标移入事件建议使用onmouseenter
添加鼠标移出事件建议使用onmousleave
注意点:
onmouseover和onmouseenter的区别
onmouseover移入到子元素,父元素也会被触发
onmouseenter移入到子元素,父元素不会被触发
onmouseout和onmouseleave
onmouseout移出到子元素,父元素也会被触发
onmouseleave移出到子元素,父元素不会被触发
焦点事件
- 监听元素获取焦点
var oInput = document.querySelector("input");
// 1.监听元素获取焦点
oInput.onfocus = function () {
console.log("onfocus");
};
- 监听元素失去焦点
// 2.监听元素失去焦点
oInput.onblur = function () {
console.log("onblur");
};
- 监听元素内容改变
oInput.onchange = function () {
console.log(this.value);
}
注意点:
onchange事件
不能时时获取数据的改变
onchange事件
只有失去焦点的时候才会执行
- 实时获取元素内容改变
oInput.oninput = function () {
console.log(this.value);
}
注意点:
oninput事件可以时时获取数据的改变, 但是有兼容性问题,IE9才能使用
// 时时监听输入框内容改变的兼容性处理
function inputChange(ele, fn) {
if("oninput" in ele){
ele.oninput = fn;
}else{
ele.onpropertychange = fn;
}
}
闭包
- 什么是闭包?
只要函数中用到了其它函数的变量, 这个函数就是一个闭包 - 闭包有什么特点?
只要闭包还在使用外界的变量, 那么外界的变量就会一直存在
function test() {
var num = 123;
return function () {
// 在这个函数中, 用到其它函数的变量
console.log(num);
}
}
var fn = test();
fn();
同步和异步
- 什么是同步?
只有前面的执行完了, 后面的才能执行,默认情况下, 编写的代码都是同步的
// 只有i加到10才不满足条件, 所以循环执行完毕i=10
for (var i = 0; i < 10; i++) {
function test() {
console.log(i);
}
}
// 当函数调用时循环已经执行完毕了, 所以拿到的是10
test();
- 什么是异步?
随时可以执行
for (var i = 0; i < 10; i++) {
(function (index) {
console.log(index);
})(i);
}
高级排他实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.selected{
background: red;
}
</style>
</head>
<body>
<ul>
<li class="selected">我是第1个li</li>
<li>我是第2个li</li>
<li>我是第3个li</li>
<li>我是第4个li</li>
<li>我是第5个li</li>
</ul>
<script>
var oLis = document.querySelectorAll("ul>li");
//利用闭包实现高级排他
//定义变量保存索引
var curIndex = 0;
//遍历所有li标签
for (var i = 0, len = oLis.length; i < len; i++){
// 保证立即执行函数中的index和当前循环的i同步
(function (index) {
oLis[index].onmouseenter = function () {
//清除curIndex索引对应的样式
oLis[curIndex].className = "";
//给index对应索引添加样式
oLis[index].className = "selected";
//保存添加样式的索引值
curIndex = index;
}
})(i);
}
</script>
</body>
</html>
定时器
- JavaScript中常用的有两种定时器
反复执行的定时器
只执行一次的定时器 - 反复执行的定时器
第一个参数: 到指定事件之后执行的回调函数
第二个参数: 指定间隔的时间
返回值: 返回当前定时器的ID
var timerId = null;
oStartBtn.onclick = function () {
timerId = setInterval(function () {
console.log("每个多少毫秒执行一次");
}, 1000);
- 只执行一次的定时器
第一个参数: 到指定事件之后执行的回调函数
第二个参数: 指定间隔的时间
返回值: 返回当前定时器的ID
timerId = setTimeout(function () {
console.log("多少毫秒之后执行一次");
}, 1000);
- 清除定时器
oEndBtn.onclick = function () {
clearInterval(timerId);
clearTimeout(timerId);
}
注意点:
开启定时器之前,一般要先清除定时器,这样可以避免重复开启定时器引发的bug
时间计算
// 1.获取到当前的时间
var now = new Date();
// console.log(now);
// 可以通过valueOf方法获取调用者距离1970/1/1相差的毫秒
// console.log(now.valueOf());
// 2.创建一个指定的时间
var date = new Date("2018/11/11 23:59:59");
// console.log(date.valueOf());
// 需求: 要求计算当前时间距离指定时间相差的天数/小时/分钟/秒钟
// 3.计算当前时间距离未来时间的毫秒
// 注意点: 时间对象可以直接进行算数运算, 系统会自动调用valueOf方法
var time = date - now;
console.log(time);
// 将获取到的相差的毫秒转换为秒
var allSecond = time / 1000;
console.log(allSecond);
// 计算天数
var d = parseInt(allSecond / (60 * 60 * 24));
console.log(d);
//计算小时数
// 计算小时
// allSecond / (60 * 60) == 计算总共相差的小时
// %24 == 计算除开天数之后相差的小时
var h = allSecond / (60 * 60) % 24;
console.log(h);
// 计算分钟
// allSecond / 60 == 计算总共相差的分钟
// %60 === 计算除开天数和小时相差的分钟
var m = allSecond / 60 % 60;
console.log(m);
// 计算秒钟
var s = allSecond % 60;
console.log(s);
函数节流
- 什么是函数节流?
函数节流就是降低性能消耗, 将频繁调用的函数修改为间隔多长时间调用一次
var oInput = document.querySelector("input");
// 2.时时监听input内容的变化
var timerId = null;
inputChange(oInput, function () {
var self = this;
clearTimeout(timerId);
// console.log("发送一次请求到服务器", this.value);
//使用一次性定时器,延迟获取输入框内容的请求
timerId = setTimeout(function () {
console.log("发送一次请求到服务器", self.value);
}, 1000);
});
function inputChange(ele, fn) {
if("oninput" in ele){
ele.oninput = fn;
}else{
ele.onpropertychange = fn;
}
}
事件对象
- 什么是事件对象?
当注册的事件被触发的时候, 系统就会自动创建一个事件对象, 并且返回给我们,事件对象就是一个系统自动创建的对象
注意点:
在高级版本的浏览器中, 会自动将事件对象传递给回调函数
在低级版本的浏览器中, 不会自动将事件对象传递给回调函数
在低级版本的浏览器中, 需要通过window.event来获取事件对象
//兼容低版本浏览器写法
event = event || window.event;
- 阻止默认元素默认事件的三种方法
// 1.企业开发推荐
return false;
// 2.禁用默认行为
// 注意点: 高级版本浏览器支持
event.preventDefault();
event.returnValue = false; // 老版本IE
事件传递阶段
- 事件的三个阶段
1.捕获阶段 (从外向内)
2.当前目标阶段
3.冒泡的阶段 (从内向外)
注意点:
事件的状态只有两种,要么捕获和当前,要么当前和冒泡
- 如何设置事件到底是捕获还是冒泡?
需要通过addEventListener
方法
因为这个方法接收三个参数
第一个参数: 事件的名称
第二个参数: 回调函数
第三个参数: false冒泡 / true 捕获
var oBox = document.querySelector(".box");
var oFDiv = document.querySelector(".father");
var oSDiv = document.querySelector(".son");
oBox.addEventListener("click", function (event) {
event = event || window.event;
console.log(event.eventPhase, "box");
}, false);
oFDiv.addEventListener("click", function (event) {
event = event || window.event;
console.log(event.eventPhase, "father");
}, false);
oSDiv.addEventListener("click", function () {
console.log(event.eventPhase, "son");
}, false);
注意点:
onXXXX的属性, 不接收任何参数, 所以默认就是冒泡
attachEvent方法, 只能接收两个参数, 所以默认就是冒泡
所以如果想指定为捕获, 只能使用addEventListener方法
- 阻止事件冒泡方法
// 阻止事件冒泡,给哪个事件添加哪个事件就会阻止冒泡
// 适用于高级版本的浏览器
event.stopPropagation();
// 适用于低级版本的浏览器
event.cancelBubble = true;