1.事件
网页中的每个元素都可以产生某些事件。 比如:当用户单击按钮时,就发生一个鼠标单击(onclick)事件。 当用户点击提交按钮时,就发生一个提交数据(onsubmit)事件。 事件是可以被侦测到的行为。 每个元素都可以产生某些可以触发JavaScript函数的事件。
javaScript中的常用事件:
1.1.javaScript中绑定事件方式
在javaScript中,给DOM元素绑定事件有三种方式:侵入式、绑定式、监听函数式。
侵入式事件方式:将javaScript事件直接写在html标签中
<div onclick="add()">点我</div>
<script>
//事件处理函数
function add(){
console.log('点击了div对象');
}
</script>
注意:此种方式的缺点是:javaScript事件与HTML代码混杂在一起。
绑定式事件方式:通过DOM对象,使用javaScript代码绑定一个事件
<div>点我</div> <script> let divObj = document.getElementsByTagName('div')[0]; //function()匿名函数就是事件处理函数 divObj.onclick = function(){ console.log('点击了div对象'); } </script>
注意:此种方式的优点是:
- 行间和事件分离。
- 可以给元素动态添加事件。
监听函数式事件方式:
<div>点我</div> <script> let divObj = document.getElementsByTagName('div')[0]; divObj.addEventListener('click',function(){ console.log('点击了div对象'); },false); </script>
注意:addEventListener函数的三个参数:
- 事件名(没有前缀on)。
- 事件处理函数。
- 布尔类型(一般为false)。true:进行事件捕获; false:不进行事件捕获;
1.2.事件对象-event
event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
1.2.1.鼠标坐标的使用
<head>
<meta charset="utf-8">
<title></title>
<style>
div{
width: 200px;
height: 200px;
background-color: blue;
margin: 100px;
}
</style>
</head>
<body>
<div><div>
<script>
document.getElementsByTagName('div')[0].onmousemove = function(event){
console.log('相对视口坐标:'+event.clientX+','+event.clientY);
console.log('相对触发事件对象坐标:'+event.offsetX+','+event.offsetY);
}
</script>
</body>
1.2.2.keyCode的使用
//获取键盘按键的keyCode
document.onkeydown = function(event){
console.log(event.keyCode);
}
常用按键的keyCode值:回车13, 空格32,上38,下40,左37,右39
1.3.事件冒泡与事件捕获
在页面上的一块可视区域中,其中可能会包括父元素可视区域与子元素可视区域。
此时,如果用户触发了子元素的某个事件,而父元素也具有相同的事件,那么事实上,我们并不能确定:用户到底是想触发子元素事件,还是想触发父元素事件。
解决这个问题的思路是:设计两种事件流:
- 当用户触发了子元素事件时,先触发子元素事件,再触发父元素事件。这就是事件冒泡。(默认)
- 当用户触发了子元素事件时,先触发父元素事件,再触发子元素事件。这就是事件捕获。
下面演示事件冒泡:
<head>
<style>
div{
width: 200px;
height: 200px;
background-color: red;
}
div p{
width: 100px;
height: 100px;
background-color: blue;
}
</style>
</head>
<body>
<div>
<p></p>
</div>
<script>
let divObj = document.getElementsByTagName('div')[0];
let pObj = divObj.getElementsByTagName('p')[0];
divObj.onclick = function(){
alert('父元素的点击事件被触发');
}
pObj.onclick = function(){
alert('子元素的点击事件被触发');
}
</script>
</body>
阻止事件冒泡: event.cancelBubble = true;
pObj.onclick = function(event){
alert('子元素的点击事件被触发');
event.cancelBubble = true;
}
1.4.浏览器默认行为
默认行为:在某些事件中,浏览器内置了一些默认的功能。 如:单击鼠标右键会弹出菜单、提交按钮默认提交动作、按下字母键会输入一个字母等。 如果这些默认行为不能满足我们需要的功能,那么可以阻止默认行为,重写我们希望的行为。 阻止默认行为很简单,在事件处理函数中调用preventDefault方法即可。 阻止默认行为: event.preventDefault();
下面是一个自定义右键菜单案例:
<ul>
<li>右键菜单项1</li>
<li>右键菜单项2</li>
<li>右键菜单项3</li>
</ul>
<script>
let ulObj = document.getElementsByTagName('ul')[0];
ulObj.style.border = 'solid 1px #666';
ulObj.style.width = '100px';
ulObj.style.position = 'absolute';
ulObj.style.display = 'none';
document.oncontextmenu = function(event){
ulObj.style.display = 'block';
ulObj.style.left = event.clientX+'px';
ulObj.style.top = event.clientY+'px';
event.preventDefault();
}
ulObj.onclick = function(){
this.style.display = 'none';
}
</script>
1.5.表单元素事件
1.5.1.表单元素常用事件
1.5.2.表单验证
表单是Web应用中的一个重要组成部分,通过表单,可以让用户与服务器端进行交互。
通常的做法是:用户通过页面表单中的各种控件(文本框、单选按钮、下拉列表等等),填入数据,表单再将这些数据发送给服务器端,进行业务处理。
但是,用户在填入数据的过程中,很有可能会填入错误的数据。此时,就需要在页面上,对用户输入的数据进行合法性验证,以保证用户必须填入正确的数据,进而保证发送给服务器端的数据都是正确的。
常用的表单验证有:
- 非空验证
- 长度验证
- 数字验证
- 日期时间格式验证
- 邮箱地址验证
- 网址验证
- … …
<h3>登陆</h3> <form> 用户名:<input type="text" id="userName"><br> 密码:<input type="password" id="password"><br> <input type="button" value="提交" onclick="checkForm()"> </form> <script> function checkForm(){ let userName = document.getElementById('userName'); let password = document.getElementById('password'); //用户名非空验证 if(userName.value==''){ alert('用户名不能为空!'); return; } //密码非空验证 if(password.value==''){ alert('密码不能为空!'); return; } //密码长度必须为六位 if(password.value.length!=6){ alert('密码长度必须为6位!'); return; } //密码必须全部为数字 if(isNaN(password.value)){ alert('密码必须全部为数字!'); return; } alert('提交'); } </script>
2.DOM编程实际案例
2.1.时钟
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>时钟</title> </head> <body> <p id="myclock" style="font-size:24px"></p> <button id="startBtn">开始</button> <button id="stopBtn">停止</button> <script> let myclock = document.getElementById("myclock"); let startBtn = document.getElementById("startBtn"); let stopBtn = document.getElementById("stopBtn"); callback(); let mytimer = setInterval(callback, 1000); function callback() { var mydate = new Date(); myclock.innerHTML = mydate.getHours() + ":" + mydate.getMinutes() + ":" + mydate.getSeconds(); } //启动按钮事件 startBtn.onclick = function() { if (mytimer == null) { mytimer = setInterval(callback, 1000); } }; //停止按钮事件 stopBtn.onclick = function() { clearInterval(mytimer); mytimer = null; }; </script> </body> </html>
2.2.全选
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>全选</title> </head> <body> 全选<input class="btn" type="checkbox"> <ul> <li><input type="checkbox">杜比环绕,家庭影院必备,超真实享受</li> <li><input type="checkbox">NVDIA 99999GT 2G 1024bit极品显卡,不容错过</li> <li><input type="checkbox">精品热卖,高清晰,45寸LED电视</li> <li><input type="checkbox">Sony索尼家用最新款笔记本</li> <li><input type="checkbox">华为,荣耀3C,超低价,性价比奇高</li> </ul> <script> let btn = document.getElementsByClassName('btn')[0]; let inputArr = document.getElementsByTagName('ul')[0].getElementsByTagName('input'); btn.onclick = function() { let bool = btn.checked; for (let i = 0; i < inputArr.length; i++) { inputArr[i].checked = bool; } } </script> </body> </html>
2.3.图片轮播
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>图片轮播</title> <style> #lunbo { width: 1226px; height: 460px; position: relative; margin: 0 auto; } #lunbo img { width: 1226px; height: 460px; position: absolute; left: 0; top: 0; display: none; } </style> </head> <body> <div id="lunbo"> <img src="img/lunbo1.jpg"> <img src="img/lunbo2.jpg"> <img src="img/lunbo3.jpg"> <img src="img/lunbo4.jpg"> <img src="img/lunbo5.jpg"> <img src="img/lunbo6.jpg"> </div> <script> let imgArr = document.getElementById('lunbo').getElementsByTagName('img'); //图片数量 let imgNum = imgArr.length //用此索引来跟踪图片轮播顺序(第一张图片索引即为0) let index = 0; //初始化第一张图片 imgArr[0].style.display = 'block'; //每隔3秒轮播一张图片 setInterval(function(){ index++; //如果轮播到最后一张图片,那么索引就归零 if (index > imgNum - 1) { index = 0; } //先隐藏所有图片 for (let i=0;i<imgNum; i++) { imgArr[i].style.display = 'none'; } //再显示当前图片 imgArr[index].style.display = 'block'; }, 3000); </script> </body> </html>
2.4.图片轮播(过渡效果)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>图片轮播(过度效果)</title> <style> #lunbo { width: 1226px; height: 460px; position: relative; margin: 0 auto; } #lunbo img { width: 1226px; height: 460px; position: absolute; left: 0; top: 0; opacity: 0; /*display: none;*/ } </style> </head> <body> <div id="lunbo"> <img src="img/lunbo1.jpg"> <img src="img/lunbo2.jpg"> <img src="img/lunbo3.jpg"> <img src="img/lunbo4.jpg"> <img src="img/lunbo5.jpg"> <img src="img/lunbo6.jpg"> </div> <script> let imgArr = document.getElementById('lunbo').getElementsByTagName('img'); //图片数量 let imgNum = imgArr.length; //当前图片索引 let index = 0; //上一张图片索引 let preIndex = index; //当前图片初始透明度 let opacityValue = 0; //上一张图片初始透明度 let preOpacityValue = 1; //初始化第一张图片 imgArr[index].style.opacity = 1; setInterval(function() { //每次切换时,确定当前图片索引与上一张图片索引 preIndex = index; index++; //判断是否进行下一轮轮播 if (index > imgNum-1) { index = 0; } //上一张图片隐藏 hideImg(); //当前图片显示 showImg(); }, 3000); function showImg() { //设置当前显示图片透明度初始值 opacityValue = 0; //淡入动画 let time = setInterval(function() { opacityValue += 0.05; if (opacityValue >= 1) { opacityValue = 1; clearInterval(time); } imgArr[index].style.opacity = opacityValue; }, 40); } function hideImg() { //设置上一张隐藏图片透明度初始值 preOpacityValue = 1; //淡出动画 let time = setInterval(function() { preOpacityValue -= 0.05; if (preOpacityValue <= 0) { preOpacityValue = 0; clearInterval(time); } imgArr[preIndex].style.opacity = preOpacityValue; }, 40); } </script> </body> </html>
2.5.放大镜
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>放大镜</title> <style> #fdj { position: relative; width: 450px; height: 450px; } #fdj img{ width: 450px; height: 450px; } #fdj .mengban { position: absolute; display: none; width: 225px; height: 225px; background-color: yellow; opacity: 0.4; cursor: move; left: 0; top: 0; } #fdj .fdjBox { position: absolute; width: 450px; height: 450px; top: 0; left: 460px; display: none; } </style> </head> <body> <!--这里是大图片--> <div id="fdj"> <img src="img/dazi.jpg"> <div class="mengban"></div> <div class="fdjBox"></div> </div> <script> <!-- onload能保证图片也加载完毕 --> window.onload = function() { let fdj = document.getElementById('fdj'); let mengban = fdj.getElementsByClassName('mengban')[0]; let fdjBox = fdj.getElementsByClassName('fdjBox')[0]; //图片尺寸 let imgWidth = fdj.getElementsByTagName('img')[0].width; fdj.onmousemove = function(event) { //这里获取了蒙板的left和top(offsetLeft是fdj距离视口的位置) let left = event.clientX - this.offsetLeft - imgWidth / 2 / 2; let top = event.clientY - this.offsetTop - imgWidth / 2 / 2; //console.log(left + ',' + top); if (left < 0) { left = 0; } if (left > this.offsetWidth - imgWidth/2) { left = this.offsetWidth - imgWidth/2; } if (top < 0) { top = 0; } if (top > this.offsetHeight - imgWidth/2) { top = this.offsetHeight - imgWidth/2; } mengban.style.left = left + 'px'; mengban.style.top = top + 'px'; mengban.style.display = 'block'; fdjBox.style.backgroundImage = 'url(img/dazi.jpg)'; fdjBox.style.backgroundRepeat = 'no-repeat'; fdjBox.style.backgroundPosition = -left * 2 + 'px' + ' ' + -top * 2 + 'px'; fdjBox.style.display = 'block'; } fdj.onmouseout = function() { mengban.style.display = 'none'; fdjBox.style.display = 'none'; } } </script> </body> </html>
2.6.走马灯
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>走马灯</title> <style> #container { width: 750px; height: 198px; margin: 0 auto; display: flex; } #container > img{ width: 55px; height: 198px; } #container div{ position: relative; width: 640px; height: 198px; overflow: hidden; display: flex; } #container div ul { list-style: none; margin: 0; padding: 0; position: absolute; width: 640px; height: 198px; left: 0px; top: 0px; display: flex; } #container div ul li { width: 160px; height: 198px; } </style> </head> <body> <!--图片尺寸:160*198--> <div id="container"> <img src="img/left.jpg"> <div> <ul> <li><a href="#"><img src="img/zmd1.jpg"></a></li> <li><a href="#"><img src="img/zmd2.jpg"></a></li> <li><a href="#"><img src="img/zmd3.jpg"></a></li> <li><a href="#"><img src="img/zmd4.jpg"></a></li> </ul> </div> <img src="img/right.jpg"> </div> <script> window.onload = function() { let container = document.getElementById('container'); let scoll = container.getElementsByTagName("ul")[0]; let imgArr = document.querySelectorAll('#container > img'); let btnLeft = imgArr[0]; let btnRight = imgArr[1]; //滚动速度 let speed = 5; //滚动方向(初始向右) let fangxiang = 1; //获取图片数量 let imgNum = scoll.getElementsByTagName("img").length; //获取图片宽度 let imgWidth = scoll.getElementsByTagName("img")[0].width; //获取滚动条宽度 let scollWidth = imgNum * imgWidth; //给滚动条加一倍的内容 scoll.style.width = scollWidth * 2 + "px"; scoll.innerHTML += scoll.innerHTML; //滚动条初始位置 scoll.style.left = "-" + scollWidth + "px"; let myTimer = setInterval(gundong, 40); function gundong() { if (fangxiang == 1) { if (scoll.offsetLeft >= 0) { scoll.style.left = "-" + scollWidth + "px"; } } else { if (scoll.offsetLeft <= scollWidth * -1) { scoll.style.left = 0 + "px"; } } scoll.style.left = scoll.offsetLeft + (speed * fangxiang) + "px"; } btnLeft.onmouseover = function() { fangxiang = -1; }; btnRight.onmouseover = function() { fangxiang = 1; }; scoll.onmouseover = function() { clearInterval(myTimer); } scoll.onmouseout = function() { myTimer = setInterval(gundong, 40); } } </script> </body> </html>