WEB前端第三十二课——js事件处理-文档、焦点
1.文档事件
主要是指添加给整个文档的事件,文档事件中,绝大部分不需要用户触发调用,而是通过文档的不同状态进行自动执行
主要事件:
① load / error,加载成功/失败事件
② DOMContentLoaded,当DOM加载完成时触发事件
③ beforeunload,页面(文档)发生卸载时触发事件
④ readystatechange,文档加载状态判断事件
⑤ resize,文档大小发生改变时的回调事件
2.load / error
load事件在节点加载成功时自动触发
error时间在节点加载失败时自动触发
语法:元素/文档(node).onload / onerror = function(){ };
<body> <img src="Images/Model.jpg" alt=""> <script> var img=document.querySelector('img'); img.onload=function () { console.log('图片加载成功!'); } img.onerror=function () { console.log('图片加载Failed!'); } </script>
3.DOMContentLoaded
与 load事件的区别是触发时机不一样,先触发DOMContentLoaded事件,后触发 load事件
DOM文档加载的步骤:
① 解析HTML结构
② 加载外部脚本和样式表文件
③ 解析并执行脚本代码
④ DOM树构建完成 ——☛触发DOMContentLoaded事件执行
⑤ 加载图片等外部文件
⑥ 页面加载完成 ——☛触发load事件执行
由此看出,样式文件的加载会阻塞脚本执行
即,如果把一个内部脚本 <script>元素放在了一个 <link>后面,在页面没有完成解析时脚本不会触发执行,直至样式文件加载完成之后。
注意,DOMContentLoaded事件只能使用DOM2方式绑定,不存在DOM0绑定方式!
4.beforeunload
页面发生卸载时触发事件(页面刷新和关闭页面之前),通常情况下配合 event .returnValue使用
一般情况下都是直接添加到body上面,如果没有在body上添加本事件,则需要在 window上添加
语法示例:window .onbeforeunload=function(){
event .returnValue='';
return'信息已修改是否确认离开?'
};
注意,beforeunload事件中弹出的对话框一般情况下不允许用户修改,只能采用默认对话框,且在beforeunload关联的回调函数中也不支持alert弹出框
5.readystatechange
当 document的 readyState改变时触发这个事件(仅第二阶段)
document .readyState的三个属性值:
loading,加载DOM中
interactive,加载外部资源
complete,加载完成
而 readystatechange事件正是这个状态发生改变时调用的事件
调用方式可以是 DOM0级事件,也可以是DOM2级事件
6.事件测试
<html lang="en"> <head> <meta charset="UTF-8"> <title>文档事件</title> <style> img{ width: 300px; } </style> </head> <body> <img src="Images/Model.jpg" alt=""> <script> var img=document.querySelector('img'); img.onload=function () { console.log('图片加载成功!'); } img.onerror=function () { console.log('图片加载Failed!'); } console.log('页面加载状态:'+document.readyState); document.addEventListener('readystatechange',function () { console.log('页面加载状态变化:'+document.readyState); }); document.addEventListener('DOMContentLoaded',function () { console.log('文档DOM树构建完成'); }); window.onload=function () { console.log('浏览器窗口加载完成!') } </script> </body> </html>
7.resize
浏览器窗口变化事件
<script> window.onresize=function(){ console.log('width:'+document.documentElement.clientWidth); console.log('height:'+document.documentElement.clientHeight); } </script>
js中为了追求变化的敏感度,将 resize事件的响应时间设置为了0,也就是说每一次的文档大小改变都会立即调用本事件
这就造成了 一次变化 却发生了 不止一次 的resize事件调用
为了解决这个问题可以采用一种延迟的写法来实现。代码如下:
<script> var flag=true window.onresize=function(){ var w=document.documentElement.clientWidth; var h=document.documentElement.clientHeight; if (flag==true){ console.log('(w,h):('+w+','+h+')'); flag=false; setTimeout(function () { flag=true; },1000); } } </script>
8.焦点事件
在js中当前正在和用户发生交互的节点称为焦点,包括获取焦点(focus)和失去焦点(blur)两种情况
获取焦点和失去焦点都既可以使用DOM0绑定也可以使用DOM2绑定,自动触发事件执行
语法:元素节点 .onfocus / onblur = function(){ };
注意,这两种事件均不支持事件冒泡,只有当前节点触发调用
如果需要传递触发,则需要使用DOM2绑定事件中的捕获方式
事件本身的书写格式:元素节点 .focus() / blur(); ,(方法)代表获取焦点 / 失去焦点
<body> Name:<input type="text" class="name"> Code:<input type="text" class="code"> <script> var code=document.querySelector('.code'); code.onfocus=function(){ code.setAttribute('placeholder','请设置6位数密码!'); }; code.onblur=function(){ if (code.length!==6){ code.setAttribute('style','border:1px solid red'); alert('密码格式不符合要求,请重新设置。'); //先于setAttrbute执行 }; }; </script> </body>
9.用户注册界面
<html lang="en"> <head> <meta charset="UTF-8"> <title>用户注册界面</title> <style> input{ display: inline-block; outline: none; height: 20px; line-height: 30px; } .boxName{ display: inline-block; padding: 0; width: 80px; } .submit{ display: inline-block; margin-left: 60px; } .borderGreen{ border: 2px solid darkgreen; } .fontGreen{ color: darkgreen; font-weight: bold; } .borderRed{ border: 2px solid red; } .fontRed{ color: red; } .idtCodePic{ width: 177px; height: 50px; line-height: 50px; text-align: center; /*word-spacing: 20px; 对字符无效*/ letter-spacing: 10px; background-image: url("Images/idtCodePic.jpg"); margin-left: 85px; font-size: 30px; } .idtCodePic:hover{ cursor: pointer; } </style> </head> <body> <p> <span class="boxName">用户名:</span> <input type="text" class="userName"> <span class="nameTips"></span> </p> <p> <span class="boxName">手机号码:</span> <input type="text" class="phoneNumber"/> <span class="phoneTips"></span> </p> <p> <span class="boxName">登录密码:</span> <input type="text" class="loginCode"> <span class="loginTips"></span> </p> <p> <span class="boxName">确认密码:</span> <input type="text" class="confirmCode"/> <span class="confirmTips"></span> </p> <span style="font-size: 12px;color: #b3d4fc;float: left; width: 25px;height: 50px;margin-left: 50px">点击图片切换</span> <div class="idtCodePic"></div> <p> <span class="boxName">验证码:</span> <input type="text" class="idtCode"/> <span class="idtTips"></span> </p> <button class="submit" disabled>提交注册</button> <script> var userName=document.querySelector('.userName'); //name不能作为变量声明! var nameTips=document.querySelector('.nameTips'); var phoneNumber=document.querySelector('.phoneNumber'); var phoneTips=document.querySelector('.phoneTips'); var loginCode=document.querySelector('.loginCode'); var loginTips=document.querySelector('.loginTips'); var confirmCode=document.querySelector('.confirmCode'); var confirmTips=document.querySelector('.confirmTips'); var idtCodePic=document.querySelector('.idtCodePic'); var idtCode=document.querySelector('.idtCode'); var idtTips=document.querySelector('.idtTips'); var submit=document.querySelector('.submit'); // 用户名内容设置 userName.onfocus=function(){ userName.setAttribute('placeholder','不少于两位字符!'); }; userName.onblur=function(){ if (userName.value.length>=3){ nameTips.innerHTML='通过'; nameTips.setAttribute('class','fontGreen'); userName.setAttribute('class','borderGreen'); }else{ nameTips.innerHTML='格式不符合要求,请重新填写'; nameTips.setAttribute('class','fontRed'); userName.setAttribute('class','borderRed'); } checkAllInfo(); }; // 手机号码内容设置 phoneNumber.onfocus=function(){ phoneNumber.setAttribute('placeholder','请填写11位手机号码!'); }; phoneNumber.onblur=function(){ if (phoneNumber.value.length==11&&phoneNumber.value[0]==1){ phoneTips.innerHTML='通过'; phoneTips.setAttribute('class','fontGreen'); phoneNumber.setAttribute('class','borderGreen'); }else{ phoneTips.innerHTML='格式不符合要求,请重新填写'; phoneTips.setAttribute('class','fontRed'); phoneNumber.setAttribute('class','borderRed'); } checkAllInfo(); }; // 登录密码内容设置 loginCode.onfocus=function(){ loginCode.setAttribute('placeholder','请设置6~12位数字或字母!'); }; loginCode.onblur=function(){ if (loginCode.value.length>=6&&loginCode.value.length<=12){ loginCode.setAttribute('class','borderGreen'); loginTips.innerHTML='通过'; loginTips.setAttribute('class','fontGreen'); }else{ loginCode.setAttribute('class','borderRed'); loginTips.innerHTML='密码格式不符合要求,请重新设置'; loginTips.setAttribute('class','fontRed'); } checkAllInfo(); }; // 确认密码内容设置 confirmCode.onfocus=function(){ confirmCode.setAttribute('placeholder','请确认上述密码!'); }; confirmCode.onblur=function(){ if (confirmCode.value==loginCode.value&&confirmCode.value!=''){ confirmCode.setAttribute('class','borderGreen'); confirmTips.innerHTML='通过'; confirmTips.setAttribute('class','fontGreen'); }else{ confirmCode.setAttribute('class','borderRed'); confirmTips.innerHTML='密码不符合要求,请重新确认'; confirmTips.setAttribute('class','fontRed'); } checkAllInfo(); }; // 验证码图片内容设置 function creatIdtCode() { var idtCodeSet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var maxNum=idtCodeSet.length; var idtCodeVal=''; for (var i=0;i<5;i++){ var index=Math.floor(Math.random()*maxNum); var idtCodeTemp=idtCodeSet[index]; idtCodeVal+=idtCodeTemp; } return idtCodeVal; } idtCodePic.innerHTML=creatIdtCode(); idtCodePic.onclick=function(){ var newIdtCode=creatIdtCode(); console.log(newIdtCode); idtCodePic.innerHTML=newIdtCode; }; idtCodePic.setAttribute('letter-spacing','20px'); //此处设置无效!! // 验证码内容设置 idtCode.onfocus=function(){ idtCode.setAttribute('placeholder','请输入上述图片内验证码!'); }; idtCode.onblur=function(){ if (idtCode.value==idtCodePic.innerHTML){ idtCode.setAttribute('class','borderGreen'); idtTips.innerHTML='通过'; idtTips.setAttribute('class','fontGreen'); }else{ idtCode.setAttribute('class','borderRed'); idtTips.innerHTML='验证码错误,请重新填写'; idtTips.setAttribute('class','fontRed'); } checkAllInfo(); }; // 提交注册按钮设置 function checkAllInfo(){ if (nameTips.innerHTML=='通过'&&phoneTips.innerHTML=='通过'&&loginTips.innerHTML=='通过' &&confirmTips.innerHTML=='通过'&&idtTips.innerHTML=='通过'){ submit.removeAttribute('disabled'); }else { submit.setAttribute('disabled','disabled'); } } </script> </body> </html>
10.滚动事件
scroll事件会在文档或元素发生滚动操作时触发
① 文档滚动事件
scrollTop,表示滚动条上下滚动的距离
scrollLeft,表示滚动条左右滚动的距离
注意,scrollTop和 ScrollLeft 距离没有计量单位,实际上是文档滚动的距离
两个属性不但可以读取,还可以赋值!书写格式:body节点 .scrollTop/.scrollLeft=value;
语法:IE环境,document .documentElement .scrollTop/.scrollLeft;
非IE环境,document .body .scrollTop/.scrollLeft;
为解决兼容性问题,在使用时可以采用“||”(或)的方式:
document .body .scrollTop/.scrollLeft || document .documentElement .scrollTop/.scrollLeft;
② 元素滚动事件
元素发生滚动时,不存在兼容性问题,但前提是,必须存在滚动条
元素的滚动条可以通过 overflow相关属性实现
overflow属性值:
visible,默认值,溢出内容不会被修剪,会呈现在元素框之外
hidden,溢出内容会被修剪,且不可见
auto,如果溢出内容被修剪,浏览器会显示滚动条以便查看
scroll,浏览器会显示滚动条,以便查看溢出内容
overflow-x和 overflow-y属性使用方法与overflow基本相同
语法:元素节点 .scrollTop / scrollLeft;
注意,可以获取元素位移距离,也可以写入,书写格式:元素节点 .scrollTop/.scrollLeft=value;
11.滚动事件代码
<html lang="en"> <head> <meta charset="UTF-8"> <title>滚动事件</title> <style> body{ width: 3000px; height: 5000px; background: linear-gradient(to bottom,lightblue,darkorange); } div{ width: 300px; height: 200px; margin-left: 100px; background-color: lightpink; overflow-y: auto; } .divBtn{ margin-left: 100px; } .bodyBtn{ position: fixed; bottom: 10px; right: 10px; } </style> </head> <body> <div> <p>下周就开学了。</p> <p>下周就开学了。</p> <p>下周就开学了。</p> <p>下周就开学了。</p> <p>下周就开学了。</p> <p>下周就开学了。</p> <p>下周就开学了。</p> <p>下周就开学了。</p> <p>下周就开学了。</p> <p>下周就开学了。</p> <p>下周就开学了。</p> </div> <button class="divBtn">滚回首行</button> <button class="bodyBtn">返回顶部</button> <script> var divBox=document.querySelector('div'); var divBtn=document.querySelector('.divBtn'); var bodyBtn=document.querySelector('.bodyBtn'); window.onscroll=function () { var top=document.body.scrollTop || document.documentElement.scrollTop; var left=document.body.scrollLeft || document.documentElement.scrollLeft; console.log('Top:'+top+','+'Left:'+left); } // 文档页面滚动事件设置 bodyBtn.onclick=function(){ var bodyScrollBack=null; console.log(bodyBtn.firstChild.nodeValue); // 添加返回顶部速度效果 bodyScrollBack=setInterval(function () { var top=document.body.scrollTop || document.documentElement.scrollTop; top = top-100; if (top<=0){ top = 0; clearInterval(bodyScrollBack); } document.body.scrollTop=top; document.documentElement.scrollTop=top; //Chrome环境下也要设置这一句! },50); }; // 元素内容滚动事件设置 divBtn.onclick=function(){ var divScrollBack=null; divScrollBack=setInterval(function () { var top=divBox.scrollTop; top = top-10; if (top<=0){ top = 0; clearInterval(divScrollBack); } divBox.scrollTop=top; },50); } </script> </body> </html>