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的使用
//获取键盘按键的keyCodedocument.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>
