事件流

 

事件流描述的是从页面中接收事件的顺序。JavaScript 有两种截然相反的事件流概念:事件冒泡事件捕获

 

  1. 事件冒泡

 

事件冒泡即事件开始时由最具体的元素(最“近”的节点)接收,然后逐级向上传播到较为不具体的节点(文档)。

<!DOCTYPE html>

<html>

<head>

<title>Click</title>

</head>

<body>

<div id=”myDiv”>Click Me</div>

</body>

</html>

 

以上 HTML 页面中,当点击<div>元素时,click 事件的传递顺序是这样的:div节点 -> body节点 -> html节点 -> document节点。所有现代浏览器都支持事件冒泡,但具体实现上有差异。

 

  1. 事件捕获

 

事件捕获的思想是事件开始时由最不具体的元素(最“远”的节点)接收,最具体的元素最后接收到事件。

以之前的 HTML 代码为例,click 事件的传递顺序是这样的:document节点 -> html节点 -> body节点 -> div 节点。老版本的浏览器不支持事件捕获,所以不推荐使用事件捕获。

 

事件处理程序

 

事件的名字包括 click、load 和 mouseover 等,而响应某个事件的函数叫做事件处理程序(或事件侦听器),事件处理程序的名字以“on”开头,为事件指定处理程序的方式有多种。

 

  1. HTML 事件处理程序

 

给 HTML 元素添加与事件处理程序同名的 HTML 属性可以指定元素事件。

 

HTML 代码:

<input type=”button” value=”click” onclick=”clickhandle()” />

JavaScript 代码:

function clickHandle() {

alert("Hello");

}

 

以上代码在点击按钮时会弹出一个弹窗。

 

  1. DOM0 级事件处理程序

 

DOM0 级事件处理程序是给元素节点的事件处理程序属性赋一个函数。所有现代浏览器都支持 DOM0 级事件处理程序。

 

HTML 代码:

<input id=”btn” type=”button” value=”click” />

 

JavaScript 代码:

var btn = document.getElementById("btn");

btn.onclick = function() {

alert(this.value);

}

 

事件处理程序函数中,this 对象引用的是绑定事件处理程序的元素节点,所以以上代码中,当点击按钮时将弹出按钮的 value 属性值。

 

删除事件处理程序的方法:btn.onclick = null;

 

  1. DOM2 级事件处理程序

 

DOM2 级事件给元素节点定义了 addEventListener() 和 removeEventListener() 方法分别用于绑定事件处理程序和删除事件处理程序。这两个方法都接收3个参数:要处理的事件名、作为事件处理程序的绑定函数和一个可选布尔值(默认为false,通常不需要手动设置),第三个布尔值为 true 表示在捕获阶段调用事件处理程序,为 false 表示冒泡阶段调用事件处理程序。

 

IE9以上及其他流行的浏览器都支持 DOM2 级事件处理程序。

 

HTML 代码:

<input id=”btn” type=”button” value=”click” />

JavaScript 代码:

var btn = document.getElementById("btn");

function clickHandle() {

alert(this.value);

}

btn.addEventListener("click", clickHandle);

setTimeout(function() {

console.log("Stop");

btn.removeEventListener("click", clickHandle);

}, 5000);//5秒后点击按钮将不会有任何反应

 

注意,removeEventListener() 第二个参数为具体的事件处理程序函数名,如果需要删除指定事件处理程序,则应先将该事件处理程序定义为普通函数而不是直接使用匿名函数

事件对象

触发一个事件时,会产生一个事件对象,这个事件对象中包含所有与事件有关的信息。

在事件处理程序中可以访问这个事件对象。
var btn = document.getElementById("btn");
btn.onclick = function(e) {//传入事件对象
alert(e.type);//输出事件类型:"click"
}

事件对象常用的属性及方法:
1. e.target:只读,返回事件的目标(直接触发的元素节点)。
2. e.type:只读,返回事件类型。
3. e.preventDefault():取消事件的默认行为,常用场景有取消提交按钮的点击提交行为及阻止链接点击跳转等,等同于 return false。
4. e.stopPropagation():取消事件进一步捕获或冒泡。

事件类型

1. UI 事件

UI 事件指那些不一定与用户操作有关的事件。

常用的 UI 事件有:
- load:页面、图像、脚本等资源完全加载后触发的事件,应用场景:图片加载完全前加入载入一个预备显示图片。
- select:用户选择文本框(<input>或<textarea>)中的字符时触发,触发元素上有两个属性 selectionStart 和 selectionEnd 分别返回的是起始位置索引号(包括)和结束位置索引号(不包括),使用这两个属性可以读取选择的文本内容。
- scroll:滚动带滚动条的元素时触发,应用场景:返回顶部按钮。

2. 鼠标事件

鼠标事件是最常用的一类事件。

常用的鼠标事件:
- click:单击鼠标左键或按回车键触发。
- dblclick:双击鼠标触发。
- mousedown:用户按下任意鼠标键时触发。
- mouseenter:鼠标移入元素触发。
- mouseleave:鼠标移出元素触发。
- mousemove:鼠标在元素上移动时触发。

鼠标事件触发元素的事件对象上设置有两个表示客户区(页面显示的区域)坐标的属性:clientX 属性(相对左上角点的水平坐标)和 clientY 属性(相对左上角点的竖直坐标)。

3. 键盘事件

用户使用键盘时会触发键盘事件。

常用的键盘事件:
- keydown:按下任意键时触发,按住不放会重复触发。
- keypress:按下字符键时触发,按住不放会重复触发。
- keyup:释放按键时触发。

键盘事件触发元素的事件对象上设置有 keyCode 属性,用于返回按下的键对应的键码。对于 keypress 事件,触发元素事件对象上的 charCode 属性可以返回按下的字符键对应的 ASCII 码。

媒体元素

HTML5 新增了两个与媒体相关的标签:<audio> 和 <video>。

  1. 音频

 

audio 标签的使用:

<audio src="./media/audio.mp3" type="audio/mpeg" controls=”true” />Music playing...</audio>

 

  1. 视频

 

video 标签的使用:

<video src=”./video/video.mp4” type=”video/mpg” controls=”true” />Video playing...</video>

 

  1. 常用通用 API

属性:

- autoplay:可读可写,布尔值,设置音频自动播放。

- controls:可读可写,布尔值,设置隐藏或显示浏览器默认的音频插件。

- currentSrc:只读,字符串,当前播放音频文件的 URL。

- currentTime:只读,浮点数,已经播放的秒数。

- duration:只读,浮点数,音频总播放时间。

- ended:只读,布尔值,表示音频是否播放结束。

- loop:可读可写,布尔值,音频是否播放结束后重新播放。

- paused:只读,布尔值,音频是否暂停。

- volume:可读可写,浮点数,音频播放音量,取值0.0~1.0之间。

- src:可读可写,设置播放音频URL。

 

方法:

- play():开始播放。

- pause():暂停播放。

 

代码清单:

A ——事件

HTML:

<!DOCTYPE html>

<html id="top">

<head>

<meta charset="UTF-8" />

<title>WJT</title>

<link rel="stylesheet" href="./css/style.css" />

</head>

<body style="height:1500px">

 

<!-- 事件冒泡点击事件触发顺序: input -> div -> body -> html -> document -->

<!-- 事件捕获点击事件触发顺序:document -> html -> body -> div -> input -->

<div>

<!-- HTML事件处理程序 -->

<!-- 语句 -->

<input type="button" value="Click1" onclick="alert('Hello');" />

<!-- 调用函数 -->

<input type="button" value="Click2" onclick="sayHello();" />

 

<!-- DOM0级事件处理程序 -->

<input id="btn1" type="button" value="Click3" />

 

<!-- DOM2级事件处理程序 -->

<input id="btn2" type="button" value="Click4" />

 

<form id="form" action="./?name=WJT" method="POST">

<input id="btn3" type="submit" value="Submit" />

</form>

</div>

 

<img id="img" src="loading.gif" style="width:200px;height:200px;border:1px solid black;" />

<textarea id="textarea">123456abcdABCD</textarea>

<p id="parah"></p>

 

<input id="topBtn" type="button" value="回到顶部" style="position:fixed;bottom:10px;right:10px;display:none;" />

 

<script src="./js/scriptd6.js"></script>

</body>

</html>

 

JavaScript:

"use strict";

 

function sayHello() {

alert("Hello");

}

function sayBye() {

alert("Bye");

}

 

var btn1 = document.getElementById("btn1");

btn1.onclick = function() {

alert(this.value);

};

// btn1.onclick = null;//清除DOM0级事件处理程序

 

var btn2 = document.getElementById("btn2");

// btn2.addEventListener("click", function() {

//     alert(this.value);

// });//涉及移除DOM2事件处理程序时这种写法不推荐

 

btn2.addEventListener("click", sayHello);//第二个参数设为一个已包装函数的函数名方便removeEventListener()找到移除目标

btn2.addEventListener("click", sayBye);//使用DOM2级事件处理程序可以给一个事件绑定多个执行函数

btn2.removeEventListener("click", sayHello);

 

btn2.addEventListener("click", function(e) {

console.log(e.target, e.type,  e.detail);

});

 

var form = document.getElementById("form");

var btn3 = document.getElementById("btn3");

btn3.onclick = function(e) {

console.log("Button");

e.stopPropagation();//取消事件冒泡,当点击按钮后表单的点击事件不会触发

// e.preventDefault();//submit按钮不再跳转页面

return false;//等同于上句代码

}

form.onclick = function(e) {

console.log("Form");

}

 

//设置预加载图片

var imgNode = document.getElementById("img");

var img = new Image();

img.src = "https://www.2345.com/images/logo/logo_normal.png";

img.onload = function() {//当img的src指定的图片加载完后就将该图片替换loading.gif显示到页面上,否则显示的就一直是loading.gif

imgNode.src = img.src;

}

 

var textarea = document.getElementById("textarea");

var parah = document.getElementById("parah");

textarea.onselect = function() {

var str = textarea.value;

parah.innerHTML = str.slice(textarea.selectionStart, textarea.selectionEnd);//将截取到的文本内容显示到parah节点上

}

 

var topBtn = document.getElementById("topBtn");

topBtn.onclick = function() {

location.href = "#top";

}

document.body.onscroll = function() {

topBtn.style.display = "block";

}

 

 

 

B——媒体

HTML:

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8" />

<title>WJT</title>

<link rel="stylesheet" href="./css/style.css" />

</head>

<body>

 

<div>

<video src="./media/video.mp4" type="video/mpg" controls="true" />Video playing...</video>

</div>

 

<div>

<audio id="audio" src="./media/audio1.mp3" type="audio/mpeg" />Music playing...</audio>

<input id="playBtn" type="button" value="播放" />

<input id="pauseBtn" type="button" value="暂停" />

<input id="nextBtn" type="button" value="下一首" />

<input id="controlsBtn" type="button" value="使用默认插件" />

<input id="loopBtn" type="button" value="循环播放" />

<input id="volumeTurnUpBtn" type="button" value="+" />

<input id="volumeTurnDownBtn" type="button" value="-" />

<span id="time"></span><span id="length"></span>

</div>

 

<script src="./js/scriptd6.js"></script>

</body>

</html>

 

JavaScript:

"use strict";

 

var audio = document.getElementById("audio");

var playBtn = document.getElementById("playBtn");

var pauseBtn = document.getElementById("pauseBtn");

var controlsBtn = document.getElementById("controlsBtn");

var nextBtn = document.getElementById("nextBtn");

var loopBtn = document.getElementById("loopBtn");

var turnUpBtn = document.getElementById("volumeTurnUpBtn");

var turnDownBtn = document.getElementById("volumeTurnDownBtn");

 

var time = document.getElementById("time");

var len = document.getElementById("length");

 

var volume = 5;

 

// audio.autoplay = true;//自动播放

 

playBtn.onclick = function() {

audio.play();//播放

 

console.log(!audio.paused, audio.currentSrc);//播放音频URL

 

setInterval(function() {

time.innerHTML = audio.currentTime;

if (audio.ended) {//播放结束

alert("播放结束");

}

}, 1000);

 

len.innerHTML = "/" + audio.duration;//总时间

}

 

pauseBtn.onclick = function() {

audio.pause();//暂停

console.log(audio.paused);

}

 

nextBtn.onclick = function() {

audio.src = audio.currentSrc.slice(0, audio.currentSrc.indexOf("audio1.mp3")) + "audio2.mp3";

}

 

controlsBtn.onclick = function() {

audio.controls = true;//使用浏览器自带插件

console.log(audio.controls);

}

 

loopBtn.onclick = function() {

audio.loop = true;//循环播放

console.log(audio.loop);

}

 

turnUpBtn.onclick = function() {

volume = volume >= 10 ? 10 : volume + 1;

audio.volume = volume / 10;//增大音量

console.log(audio.volume);

}

 

turnDownBtn.onclick = function() {

volume = volume <= 0 ? 0 : volume - 1;

audio.volume = volume / 10;//降低音量

console.log(audio.volume);

}

 

欢迎留言