JS事件执行机制
一、JS事件知识
1.1注册事件(2种方式)
给元素添加事件,称为注册事件或绑定事件
注册事件有两种方式:传统方式和监听注册方式
传统注册方式:
利用on开头的事件onclick
<button onclick="alert("hi~")"></button>
btn.onclick=function(){}
-
特点:注册事件的唯一性
-
同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
监听注册方式
-
w3c标准 推荐方式
-
addEventListenner()他是一个方法
-
IE9之前的IE不支持此方法,可使用attachEvebt()代替
-
特点:同一个元素同一个事件可以注册多个监听器
-
按注册顺序依次执行
1.2事件监听
addEventListenner()事件监听(IE9以后支持)
eventTarget.addEventListener(type,listenner[,useCaoture])
该方法接受三个参数:
type:事件类型字符串,比如click、mouseover,注意不带on
listener:事件处理函数,事件发生时,会调用该监听函数
useCapture:可选参数,是一个布尔值,默认是false。
例:
<button>传统注册事件</button>
<button>方法监听注册事件</button>
<script>
var btns = document.querySelectorAll('button');//通过选择器来选择元素
// 1. 传统方式注册事件
btns[0].onclick = function () {
alert('hi');
}
// 2. 事件侦听注册事件 addEventListener
// (1) 里面的事件类型是字符串 必定加引号 而且不带on
// (2) 同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
btns[1].addEventListener('click', function () {
alert(22);
})
btns[1].addEventListener('click', function () {
alert(33);
})
</script>
1.3常用鼠标事件
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发.. |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
1.4事件对象
event是事件对象
event.target是返回触发事件的对象
1.5鼠标事件对象
(1)基础语法
event事件对象是事件相关的一系列信息的集合
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面的X坐标IE9+支持 |
e.pageY | 返回鼠标相对于文档页面的Y坐标IE9+支持 |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
例:获取鼠标在页面的坐标
<script>
// 鼠标事件对象 MouseEvent
document.addEventListener('click', function (e) {//通过监听事件方式
// 1. client 鼠标在可视区的x和y坐标
console.log(e.clientX);
console.log(e.clientY);
console.log('---------------------');
// 2. page 鼠标在页面文档的x和y坐标
console.log(e.pageX);
console.log(e.pageY);
console.log('---------------------');
// 3. screen 鼠标在电脑屏幕的x和y坐标
console.log(e.screenX);
console.log(e.screenY);
})
</script>
1.6常用的键盘事件
1.1.1键盘事件
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个键盘按键被松开时触发 |
onkeydown | 某个键盘按键被按下时触发 |
obkeypress | 某个键盘按键被按下时触发 注:不能识别功能键比如:ctrl shift 等 |
注意:
1.如果使用addEventListener不需要加on
2.onkeypress和前面两个的区别:不能识别功能键,比如左右箭头,ctrl、shift等
3.三个事件的执行顺序是:keydown--keypress--keyup
例:
<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>
二、BOM
2.1什么是BOM
BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。BOM 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性。
DOM
-
文档对象类型
-
DOM就是把文档当作一个对象来写
-
DOM的顶级对象是document
-
DOM主要学习的是操作页面元素
-
DOM是W3C标准规范
BOM
-
浏览器对象类型
-
把浏览器当做一个对象来看待
-
BOM顶级对象是window
-
BOM学习的是浏览器窗口交互的一些对象
-
BOM是浏览器厂商在各自浏览器上定义的,兼容性较差
2.2BOM的构成
BOM比DOM更大,它包含DOM
(1)定时器(两种 )
-
setTimeout()
-
setInerval()
setTimeout()炸弹定时器
开启定时器
window.setTimeout(调用函数,[延时的毫秒数]);
setTimeout()这个调用函数也称为回调函数callback
注意:
1.window可以省略
2.这个调用函数可以直接写函数,或者函数名或者采取字符串‘函数名()’-----不推荐 三种方式
3.延迟的毫秒数省略默认是0,如果写,必须是毫秒
4.因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。
普通函数是按照代码顺序直接调用。 简单理解: 回调,就是回头调用的意思。上一件事干完,再回头再调用这个函数。 例如:定时器中的调用函数,事件处理函数,也是回调函数。 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>
停止定时器
window.clearTimeout(timeoutID)
clearTimeout()方法取消了先前通过调用setTimeout()建立的定时器。
注意:
1.window可以省略
2.里面的参数就是定时器的标识符。
例:
<button>点击停止定时器</button>
<script>
var btn = document.querySelector('button');//监听事件触发
// 开启定时器
var timer = setTimeout(function () {
console.log('爆炸了');
}, 5000);
// 给按钮注册单击事件
btn.addEventListener('click', function () {//监听事件触发
// 停止定时器
clearTimeout(timer);
})
</script>
setInterval() 闹钟定时器
开启定时器
window.setInterval(回调函数,[间隔的毫秒数]);
setInterval()方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。
注意:
1.window可以省略
2.这个调用函数可以直接写函数,或者函数名或者采取字符串‘函数名()’三种形式
3.间隔的毫秒数省略默认是0,如果写,必须是毫秒,表示每隔多少毫秒就自动调用这个函数
4.因为定时器可能有很多,所以我们经常给定时器一个赋值一个标识符
5.第一次执行也是间隔毫秒数之后执行,之后每隔毫秒数就执行一次
例:
<script>
// 1. setInterval
setInterval(function () {
console.log('继续输出');
}, 1000);
</script>
案例:倒计时
<style>
* {
margin: 0;
padding: 0;
}
div{
background-color: red;
width: 300px;
height: 100px;
margin: 0 auto;
}
div>span {
display: inline-block;
width: 50px;
height: 50px;
background-color: #000;
color: white;
font-size: 25px;
text-align: center;
line-height: 50px;
margin-left: 15px;
margin-top: 10px;
}
div>p{
color: white;
text-align: center;
font-size: 24px;
font-weight: 400;
}
</style>
</head>
<body>
<div>
<p>本场距离结束还剩</p>
<span class="day">1</span>
<span class="hour">2</span>
<span class="minute">3</span>
<span class="second">4</span>
</div>
<script>
//获取元素
var day = document.querySelector('.day');//获取天数的盒子
var hour = document.querySelector('.hour');//获取小时的盒子
var minute = document.querySelector('.minute');//获取分钟的盒子
var second = document.querySelector('.second');//获取秒数的盒子
//创建一个新的变量存放用户返回的总毫秒数
var inputTime = new Date('2021-10-07 12:00:00');
time();//先调用一次防止 页面空白
setInterval(time, 1000);//开启定时器
function time() {
var nowTime = new Date();//返回当前时间的总毫秒数
var times = (inputTime - nowTime) / 1000;//返回剩余时间的总秒数
var d = parseInt(times / 60 / 60 / 24);//返回剩余的天数
if (d < 10) {
d = "0" + d;
}
day.innerHTML = d;//把获取的天数赋值给元素day
var h = parseInt(times / 60 / 60 % 24);//返回剩余的小时
if (h < 10) {
h = "0" + h;
}
hour.innerHTML = h;//把获取的小时赋值给元素hour
var m = parseInt(times / 60 % 60);//返回剩余的分钟
if (m < 10) {
m = "0" + m;
}
minute.innerHTML = m;//把获取的分钟赋值给元素minute
var s = parseInt(times % 60);//返回剩余的秒数
if (s < 10) {
s = "0" + s;
}
second.innerHTML = s;//把获取的秒数赋值给元素second
}
</script>
停止定时器
window.clearInterval(intervalID);
clearInterval()方法取消了先前调用setInterval()建立的定时器
注意:
1.window可以省略
2.里面的参数就是定时器的标识符
案例:发送短信倒计时
点击按钮后,该按钮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>
(2). location对象
什么是 location 对象
window对象给我们提供了location属性用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为location对象。
URL
统一资源定位符是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么去处理
URL的一般语法格式为:
protocol://host[:port]/path[/?query]#fragment http://www.itcast.cn/index.html?name=andy&age=18#link
组成 | 说明 |
---|---|
protocol | 通信协议 常用的http,ftp,maito等 |
host | 主机(域名) |
port | 端口号 可选,省略时使用方法方案的默认端口 如http的默认端口为80 |
path | 路径 由零或多个‘/’符号隔开的字符串,一般用来表示主机上的一个目录或文件地址 |
query | 参数 以键值对的形式通过&符号分隔开来 |
fragment | 片段 #后面内容 常见于链接 锚点 |
location 对象的属性
location对象属性 | 返回值 |
---|---|
location.herf | 获取或者设置 整个URL |
location.host | 返回主机 (域名) |
location.port | 返回端口号 如果未写返回----空字符串 |
location.pathname | 返回路径 |
location.search | 返回参数 |
location.hash | 返回片段 #后面内容 常见于链接 锚点 |
href和search是重点
案例:5分钟自动跳转页面
思路:1.利用定时器做倒计时效果
2.时间到了,就跳转页面。使用location.href
<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.itcast.cn';
} else {
div.innerHTML = '您将在' + timer + '秒钟之后跳转到首页';
timer--;
}
}, 1000);
</script>
三、JS执行机制
以下代码执行的结果是什么?
<script>
console.log(1);
setTimeout(function () {
console.log(3);
}, 1000);
console.log(2);
</script>
以下代码执行的结果是什么?
<script>
console.log(1);
setTimeout(function () {
console.log(3);
}, 0);
console.log(2);
</script>
3.1 JS 是单线程
JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。
3.2 同步任务和异步任务
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。
同步任务都在主线程上执行,形成一个执行栈
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事
JS的异步是通过回调函数实现的
一般而言。异步任务有三种类型:
1.普通事件,如click、resize等
2.资源加载,如load、error等
3.定时器,包括setInerval、seTimeout等
异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)
3.3 JS执行机制(事件循环)
1.先执行执行栈中的同步任务
2.异步任务(回调函数)放入任务队列中
3.一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等状态,进入执行栈,开始执行
由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为(事件循环)
3.4案例
<script>
console.log(1);
document.onclick = function() {
console.log('click');
}
setTimeout(function() {
console.log(3)
}, 3000)
console.log(2);
</script>