【十四】JavaScript之DOM中的事件操作
【1】事件操作
-
所谓的事件(Event),其实就是用户与浏览器之间的一次交互过程或交互行为。
- 例如:用户输入一段内容,用户鼠标晃动一下等等。
-
js中提供了大量的事件操作给开发者, 在用户发生事件操作以后,进行反馈,响应。
-
事件类型有很多,但是操作基本都是一样的,只是里面的代码因为事件的不同,而执行的方式,属性不同而已。
【2】事件类型
- js中针对用户与浏览器之间的交互方式不同,提供了多种类型的事件,常用的有例如:鼠标事件、键盘事件、表单事件、窗口事件等。
类型 | 事件 | 描述 |
---|---|---|
鼠标事件 | click |
鼠标点击事件 |
鼠标事件 | mouseover |
鼠标滑过事件 |
鼠标事件 | dblclick | 鼠标双击事件 |
鼠标事件 | mouseout |
鼠标离开事件 |
鼠标事件 | mouseup |
鼠标松开事件 |
鼠标事件 | mousedown | 鼠标按下事件 |
鼠标事件 | mousemove |
鼠标移动事件 |
表单事件 | focus |
获取焦点事件 |
表单事件 | blur |
失去焦点事件 |
表单事件 | change |
输入框/选择框值改变事件 |
表单事件 | select |
在文本框中选择文本时 |
表单事件 | submit |
表单提交 |
键盘事件 | keydown |
键盘按下 |
键盘事件 | keyup |
键盘松开 |
键盘事件 | onkeypress |
按下并松开 |
窗口事件 | onload | 页面加载内容完成以后自动触发当前事件 |
在js中使用事件时,必须事件名称左边加上on
例如:给一个元素绑定点击事件则是 onclick...
(1)鼠标事件
- 鼠标事件一个绑定给所有的HTML元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
* {
margin: 0;
padding: 0;
}
.btn2, .btn3, .btn4{
width: 100px;
height: 42px;
background: red;
}
.btn4{
position: absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<!-- <button class="btn1">点击跳转到百度</button>-->
<!-- <div class="btn2"></div>-->
<!-- <div class="btn3"></div>-->
<div class="btn4"></div>
<script>
// // click 点击事件
// var btn1 = document.querySelector(".btn1")
// btn1.onclick = function(){
// location.assign("https://www.baidu.com")
// }
//
// // dblclick 双击事件[一秒内连续鼠标点击2次]
// var btn2 = document.querySelector(".btn2")
// btn2.ondblclick = function(){
// btn2.style.background = "yellow";
// }
//
// // mouseover 鼠标悬放
// var btn2 = document.querySelector(".btn2")
// btn2.onmouseover = function(){
// console.log("只要鼠标在当前元素上方悬放就会触发一次")
// btn2.style.background = "orange";
// }
//
// // mouseout 鼠标离开
// var btn2 = document.querySelector(".btn2")
// btn2.onmouseout = function(){
// console.log("只要鼠标从当前元素上方离开就会触发一次")
// btn2.style.background = "red";
// }
//
// // mousedown 鼠标按下
// var btn3 = document.querySelector(".btn3")
// btn3.onmouseout = function(){
// console.log("只要鼠标从当前元素上方离开就会触发一次")
// btn3.style.background = "red";
// }
//
// // mousedown 鼠标按下
// var btn3 = document.querySelector(".btn3")
// btn3.onmousedown = function(){
// console.log("鼠标在当前元素范围内按下,就会触发事件")
// btn3.style.background = "blue";
// }
//
// // mouseup 鼠标松开
// var btn3 = document.querySelector(".btn3")
// btn3.onmouseup = function(){
// console.log("鼠标在当前元素范围内从按下变成松开,就会触发事件")
// btn3.style.background = "green";
// }
// // mousemove 鼠标移动
// var btn4 = document.querySelector(".btn4")
// btn4.onmousemove = function(event){
// console.log("鼠标在当前元素范围内移动,就会触发事件")
// // console.log(this.offsetLeft) // 距离浏览器窗口左边的宽度
// // console.log(event.clientX) // 当前事件发生时,鼠标位置距离浏览器窗口左边的宽度
// console.log(event.offsetX) // 当前事件发生时,鼠标位置距离当前元素的左边的宽度
// }
// 鼠标拖拽效果[基于原生js提供的鼠标按下事件,和鼠标移动事件]
var btn4 = document.querySelector(".btn4")
btn4.onmousedown = function(event){
// 鼠标按下
let startX = event.clientX-this.offsetLeft; // 记录每次鼠标按下时坐标
let startY = event.clientY-this.offsetTop;
btn4.onmousemove = function(e){
// 鼠标移动
this.style.left = `${e.clientX - startX}px`; // 计算鼠标移动的距离
this.style.top = `${e.clientY - startY}px`;
}
}
btn4.onmouseup = function(){
console.log("鼠标离开了当前元素范围!");
btn4.onmousemove = null;
}
</script>
</body>
</html>
(2)表单事件
- 表单事件一般是绑定表单元素的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
</style>
</head>
<body>
<div class="loginbox">
登录账号:<input type="text" name="username" placeholder="请输入账号!"><b></b><br>
登录密码:<input type="password" name="password" placeholder="请输入密码!"><br>
确认密码:<input type="password" name="password2" placeholder="请再次输入密码!"><br>
所在城市:<select name="city">
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="chongqing">重庆</option>
<option value="guiyang">贵阳</option>
</select><br>
<input type="file" name="avatar" id="">
</div>
<script>
var username = document.querySelector('input[name="username"]')
var password = document.querySelector('input[name="password"]')
// 获取焦点
username.onfocus = function(){
username.style.outline = "1px solid rgba(255, 99,99, 1)";
if(username.nextElementSibling.innerHTML){
username.value = "";
username.nextElementSibling.innerHTML = "";
}
}
// 失去焦点
username.onblur = function(){
username.style.outline = "none";
if(username.value.length<3 || username.value.length>16){
username.nextElementSibling.innerHTML = "账号的账号必须在3-16个字符之间"
}
}
// 值改变[输入框,下拉框,文件上传等]
password.onchange = function(){
console.log(password.value);
}
var city = document.querySelector('select[name="city"]');
city.onchange = function(){
console.log(city.value)
console.log(city.options.selectedIndex)
}
var avatar = document.querySelector('input[name="avatar"]');
avatar.onchange = function(){
console.dir(avatar.value);
}
</script>
</body>
</html>
(3)键盘事件
- 一般是绑定window,document,表单输入类型元素的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
</style>
</head>
<body>
<form action="https://httpbin.org/post" method="post">
<input type="text" name="username">
<button>登录</button>
</form>
<script>
// // keyup 键松开
// document.onkeyup = function(event){
// console.log(`本次按了:${event.keyCode}键`)
// }
//
// // keydown 键按下
// document.onkeydown = function(event){
// console.log(`本次按了:${event.keyCode}键`)
// }
// var username = document.querySelector('input[name="username"]')
// username.onkeyup = function(){
// if(username.value.length<3 || username.value.length>16){
// username.style.outline = "1px solid red";
// }else{
// username.style.outline = "1px solid blue";
// }
// }
// 回车键直接提交表单
window.onkeyup = function(event){
if(event.keyCode === 13){
console.log("按了回车键");
document.querySelector('form').submit(); // 直接触发事件
}
}
</script>
</body>
</html>
(4)窗口事件
- 窗口事件一般只给window绑定。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
// // 直接执行肯定报错,我们需要让代码延时执行。
// var h1 = document.querySelector("h1"); // 这段代码执行的时候,浏览器根本不知道找到前面的内容有h1出现
// console.log(h1);
// console.log(h1.innerHTML);
// 1. 使用window.onload,保证页面内容加载完成以后才执行js代码
// 但是window.onload只能使用一次,多次绑定函数,只会识别最后一次
window.onload = function(){
console.log("window onl oad")
var h1 = document.querySelector("h1"); // 这段代码执行的时候,浏览器根本不知道找到前面的内容有h1出现
console.log(h1);
console.log(h1.innerHTML);
}
//2. 使用setTimeout来完成延时执行,因为setTimeout的执行时在页面加载完成以后才会执行的
// 比window.onload要好用,可以使用多次。
setTimeout(()=>{
console.log("setTimeout1")
var h1 = document.querySelector("h1"); // 这段代码执行的时候,浏览器根本不知道找到前面的内容有h1出现
console.log(h1);
console.log(h1.innerHTML);
}, 0)
setTimeout(()=>{
console.log("setTimeout2")
var h1 = document.querySelector("h1"); // 这段代码执行的时候,浏览器根本不知道找到前面的内容有h1出现
console.log(h1);
console.log(h1.innerHTML);
}, 0)
</script>
</head>
<body>
<h1>标题</h1>
<script>
// window.onload = function(){
// console.log("页面加载完成才会触发当前事件!!")
// }
console.log("hello")
</script>
</body>
</html>
【3】事件的绑定
基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
<li>1-内容</li>
<li onclick="show_data(this)">2-内容</li>
<li class="li3">3-内容</li>
<li>4-内容</li>
<li>5-内容</li>
</ul>
<script>
// var li = document.querySelector("li")
// // 动态绑定事件:在js中获取元素,并基于元素对象进行事件绑定
// li.onclick = function(){
// console.log(this.innerHTML)
// }
//
// // 静态绑定事件:在html标签中,使用属性的方式来绑定事件
// function show_data(element){
// console.log(element); // element就是当前触发事件时传递进行来的当前元素对象
// console.log(event); // 静态绑定事件触发时,当前事件对象
// }
//
// /*动态绑定在工作中更加常用*/
// // 事件解绑,绑定时是什么类型的事件,解绑时就要对当前类型事件进行赋值为null
// li.onclick = null;
/**
* addEventListner(事件类型,事件处理函数) 绑定事件
* removeEventListner(事件类型,事件处理函数) 解绑事件
* EventListner 表示事件监听器,是属于js事件操作的最新用法,
* onclick属于level1.0版本的事件处理机制,无法对同一个元素多次绑定事件处理函数,
* EventListner属于level3.0版本的事件处理机制,可以对同一个元素多次绑定事件处理函数
*/
var li3 = document.querySelector(".li3")
// 事件处理函数,可以是任意函数
var li_click = (event)=>{
console.log("li_click")
console.log(event);
console.log(event.target); // target 可以获取当前事件触发时的元素对象
}
var li2_click = (event)=>{
console.log("li2_click")
console.log(event);
console.log(event.target); // target 可以获取当前事件触发时的元素对象
}
li3.addEventListener("click", li_click);
li3.addEventListener("click", li2_click);
// 事件解绑时,要指定解绑的是哪一个函数
// li3.removeEventListener("click", li_click);
// 针对元素如果使用level3.0的事件处理机制,绑定多次事件处理函数时,
// 可以通过F12浏览器调试工具->console->EventListeners来查看
</script>
</body>
</html>
动态绑定事件[常用]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box{
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<button id="hide">隐藏</button>
<button id="show">显示</button>
<div class="box"></div>
<h1>hello</h1>
<script>
let hide = document.querySelector("#hide");
let show = document.querySelector("#show");
let box = document.querySelector(".box");
// hide.onclick = function(){
// box.style.display = "none";
// }
// show.onclick =function(){
// box.style.display = "block"
// }
// let timer = null;
// hide.onclick = function(){
// let opacity = parseFloat(getComputedStyle(box)["opacity"])
// clearInterval(timer)
// timer = setInterval(()=>{
// if(opacity<=0){
// box.style.display = "none";
// clearInterval(timer)
// }else{
// opacity-=0.02
// box.style.opacity = opacity;
// }
// },25)
// }
// show.onclick = function(){
// let opacity = parseFloat(getComputedStyle(box)["opacity"])
// box.style.display = "block";
// clearInterval(timer)
// timer = setInterval(()=>{
// if(opacity>=1){
// clearInterval(timer)
// }else{
// opacity+=0.02
// box.style.opacity = opacity;
// }
// },25)
// }
let timer = null;
hide.onclick = function(){
box.style.position = "relative"
let top = parseFloat(getComputedStyle(box)["top"])
clearInterval(timer)
timer = setInterval(()=>{
if(top == 0 ){
top-=1
}
if(top <=-1){
top*=1.4
}
if(top <= -window.outerHeight){
box.style.height="0px"
clearInterval(timer)
}
box.style.top = parseInt(top)+'px';
},24)
}
show.onclick = function(){
box.style.position = "relative"
let top = parseFloat(getComputedStyle(box)["top"])
clearInterval(timer)
box.style.height="100px";
timer = setInterval(()=>{
if(top>=0){
box.style.top="0px";
clearInterval(timer)
}else{
top*=0.9
box.style.top = parseInt(top)+'px';
}
},24)
}
</script>
</body>
</html>
静态绑定事件
- 直接给标签元素以"on+事件名"这种方式绑定事件,称之为静态绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box{
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<button onclick="hide1()">隐藏</button>
<button onclick="show1()">显示</button>
<div class="box" onm ouseover="change_color(true)" onm ouseout="change_color(false)"></div>
<script>
var box = document.querySelector(".box");
function hide1(){
// 隐藏div
let width = parseInt(getComputedStyle(box)["width"]);
let height = parseInt(getComputedStyle(box)["height"]);
let timer = setInterval(()=>{
box.style.width = --width+"px";
box.style.height = --height+"px";
if(width<1){
clearInterval(timer); // 停止定时器的执行
}
},3);
}
function show1(){
// 显示div
let width = parseInt(getComputedStyle(box)["width"]);
let height = parseInt(getComputedStyle(box)["height"]);
let timer = setInterval(()=>{
box.style.width = ++width+"px";
box.style.height = ++height+"px";
if(width>100){
clearInterval(timer); // 停止定时器的执行
}
},3);
}
function change_color(type){
if(type){
box.style.backgroundColor="blue";
}else{
box.style.backgroundColor="red";
}
}
</script>
</body>
</html>
动态绑定与静态绑定的区别
动态绑定,根据已存在的元素对象指定事件处理的,而静态绑定,实际上是根据HTML代码结合事件处理函数来处理的。所以针对元素如果属于js代码动态生成,动态绑定有可能无法处理。
以下情况使用动态绑定,就不好处理。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button class="add">添加</button>
<ul class="box">
</ul>
<script>
var add = document.querySelector(".add")
var box = document.querySelector(".box")
add.onclick = function(){
box.innerHTML+= `<li><input type="text"><button onclick="sub(this)">-</button></li>`
}
function sub(ele){
ele.parentElement.remove();
}
</script>
</body>
</html>
【4】批量绑定事件
- 表示一次性给多个元素绑定事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
<li>1-</li>
<li>2-</li>
<li>3-</li>
</ul>
<script>
var list = document.querySelectorAll("li")
// 如果循环,函数,方法中的变量尽可能使用let进行声明。
// 其他地方的变量则可以使用var声明
for(let i = 0; i<list.length; i++){
list[i].onclick = function(){
console.log(i, list[i].innerHTML);
// console.log(this.innerHTML)
}
}
// console.log(i); // for循环中使用let声明,不要使用var,否则i会变成全局变量。
</script>
</body>
</html>
【5】事件的操作
- 在事件处理函数中,可以根据event事件处理机制,在函数内部通过当前时间对象完成事件周边操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<button class="btn">点击按钮</button>
</div>
<script>
var btn = document.querySelector(".btn")
var func1 = function(event){
console.log(event); // 当前事件对象,MouseEvent 表示鼠标事件
console.log(event.target) // 触发事件的元素对象
console.log(event.timeStamp) // 触发事件时,客户端的时间戳
console.log(event.type) // 触发事件的事件类型
console.log(event.path) // 事件触发过程中的事件捕获/事件传播路径
}
btn.addEventListener("click", func1);
</script>
</body>
</html>
【6】事件的传播机制
- 事件在用户触发时,实际上在js中内部处理过程中,分2个阶段:
- 冒泡阶段与捕获阶段。
- 冒泡阶段:
- 从事件发生的最开始元素(event.target),从内层往外层,逐层查找事件处理函数,这个过程就是冒泡阶段。
- 捕获阶段:
- 从窗口(window)调用事件处理函数,从外层往内层逐步查找元素冒泡路径的过程,这就是捕获阶段。
【7】事件冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body onclick="show(this)">
<div class="box1" onclick="show(this)">
<h1>标题</h1>
<p class="p1" onclick="show(this)">
<span>文章内容</span><br>
<a href="" class="a1" onclick="return show(this)">a标签内容</a>
</p>
</div>
<script>
function show(ele){
console.log(ele);
return false; // 阻止页面跳转或表单提交
}
</script>
</body>
</html>
-
在事件触发时,事件的影响出内往外进行逐层传递,这个过程就是事件冒泡(Event Propagation),有好处也有坏处。
-
好处:
- 我们可以批量的元素操作的事件,基于事件委托让父元素进行代理绑定,避免在动态绑定时对于动态生成的HTML元素不可控的情况。
-
坏处:
- 有时候父元素与子元素绑定同类型事件时,父元素不希望被触发的事件,会因为子元素被触发了而直接执行。
-
阻止事件冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.login-btn{
border: none;
outline: none;
background: #315efb;
color: #fff;
width: 120px;
height: 48px;
line-height: 48px;
text-align: center;
border-radius: 5px;
cursor: pointer;
font-size: 18px;
}
.login-bg{
width: 100%;
height: 100%;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
display: none;
background-color: rgba(0,0,0,0.67);
}
.login-box{
width: 400px;
height: 180px;
padding: 100px;
background-color: #fff;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
</style>
</head>
<body>
<button class="login-btn">登录</button>
<div class="login-bg">
<div class="login-box">
<h2>登录</h2>
登录账号:<input type="text"><br><br>
登录密码:<input type="password" name="" id=""><br><br>
<input type="submit" value="登录">
</div>
</div>
<script>
let btn = document.querySelector(".login-btn")
let bg = document.querySelector(".login-bg")
let box = document.querySelector(".login-box")
btn.onclick = function(){
bg.style.display = "block"
}
bg.onclick = function(){
bg.style.display = "none";
}
box.onclick = function(event){
console.log("备点了")
// 阻止事件继续冒泡
event.stopPropagation()
}
</script>
</body>
</html>
【8】事件委托
- 利用事件冒泡实现事件委托(也叫事件委派)
- 基于事件冒泡的特点,让子元素被触发事件以后的事件处理函数绑定到父元素中。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>作业</title>
<style>
*{ padding: 0;margin: 0; }
ul,li{list-style: none; }
ul{
width: 868px;
height: 374px;
background: #f5f5f5;
margin: 10px auto 0;
}
ul li{
position: relative;
float: left;
margin: 1px 1px 0px;
height: 92px;
width: 122px;
}
#opacity{
position: absolute;
top: 0;
left: 0;
width: 122px;
height: 92px;
background: #000;
opacity: .8;
cursor: pointer;
}
#opacity img{
float: right;
margin: 14px 12px 10px 0px;
}
#opacity p{
color: #fff;
font-size: 11px;
text-align: center;
}
#opacity input{
display: block;
margin: 15px auto 0;
background: #f00;
width: 63px;
height: 18px;
line-height: 18px;
border: none;
border-radius: 8px;
color: #fff;
font-size: 11px;
text-align: center;
outline: none;
}
.clear{
clear: both;
}
</style>
</head>
<body>
<ul>
<li data-number="15.0">
<img src="images/1.png" alt="">
<div id="opacity">
<img src="images/lve.png" alt="">
<div class="clear"></div>
<p>关注人数 15.0万</p>
<input type="button" value="点击进入">
</div>
</li>
<li data-number="20.0"><img src="images/2.png" alt=""></li>
<li data-number="7.0"><img src="images/3.png" alt=""></li>
<li data-number="15.3"><img src="images/4.png" alt=""></li>
<li data-number="15.6"><img src="images/5.png" alt=""></li>
<li data-number="24.0"><img src="images/6.png" alt=""></li>
<li data-number="39.0"><img src="images/7.png" alt=""></li>
<li data-number="8.0"><img src="images/1.png" alt=""></li>
<li data-number="55.0"><img src="images/2.png" alt=""></li>
<li data-number="43.0"><img src="images/3.png" alt=""></li>
<li data-number="12.0"><img src="images/4.png" alt=""></li>
<li data-number="34.0"><img src="images/5.png" alt=""></li>
<li data-number="22.0"><img src="images/6.png" alt=""></li>
<li data-number="12.0"><img src="images/7.png" alt=""></li>
<li data-number="21.0"><img src="images/1.png" alt=""></li>
<li data-number="42.0"><img src="images/2.png" alt=""></li>
<li data-number="22.0"><img src="images/3.png" alt=""></li>
<li data-number="52.0"><img src="images/4.png" alt=""></li>
<li data-number="21.0"><img src="images/5.png" alt=""></li>
<li data-number="17.0"><img src="images/6.png" alt=""></li>
<li data-number="12.0"><img src="images/7.png" alt=""></li>
<li data-number="3.0"><img src="images/1.png" alt=""></li>
<li data-number="1.0"><img src="images/2.png" alt=""></li>
<li data-number="0.5"><img src="images/3.png" alt=""></li>
<li data-number="1.4"><img src="images/4.png" alt=""></li>
<li data-number="2.0"><img src="images/5.png" alt=""></li>
<li data-number="4.0"><img src="images/6.png" alt=""></li>
<li data-number="5.0"><img src="images/7.png" alt=""></li>
</ul>
<script>
// // 1. 批量绑定事件
// var list = document.querySelectorAll("li")
// var opacity = document.querySelector("#opacity")
// for(let i = 0; i<list.length; i++){
// list[i].addEventListener("mouseover", show);
// }
// function show(event){
// if(event.target.parentElement.tagName === "LI"){
// // console.log(event.target.parentElement.dataset); // 获取HTML元素中以data-开头的属性
// let num = event.target.parentElement.dataset.number;
// opacity.querySelector("p").innerHTML = `关注人数 ${num}万`
// event.target.parentElement.appendChild(opacity);
// }
// }
// 事件委托: 把子元素的事件处理函数委托给父元素触发
var ul = document.querySelector("ul")
ul.addEventListener("mouseover", show);
function show(event){
if(event.target.parentElement.tagName === "LI"){
// console.log(event.target.parentElement.dataset); // 获取HTML元素中以data-开头的属性
let num = event.target.parentElement.dataset.number;
opacity.querySelector("p").innerHTML = `关注人数 ${num}万`
event.target.parentElement.appendChild(opacity);
}
}
</script>
</body>
</html>
标签:function,console,log,DOM,JavaScript,事件,十四,document,鼠标
From: https://www.cnblogs.com/dream-ze/p/17525634.html