事宜有很多类型,不同的事宜类型具有不同的信息;

DOM2级事宜规定了下列5种事宜:

UIEvent(user Interface,用户界面)事宜,在用户与页面上的元素交互时触发;MouseEvent鼠标事宜,当用户通过鼠标在页面上实行操作时触发;KeyboardEvent键盘事宜:通过键盘在页面上实行操作时触发;HTML事宜:当浏览器窗口发生变革或发生特定的客户端/做事器交互时触发;MutationEvent变动事宜:当底层DOM构造发生变革时触发;

DOM3级在DOM2的根本上重新定义了这些事宜,并增加了一些事宜:

jsp焦点事件第56节 事宜类型Event TypeWeb前端开辟之Javascript王唯 Ruby

FocusEvent焦点事宜:当元素得到或失落去焦点时触发;WheelEvent滚轮事宜:当利用鼠标滚轮(或类似设备)时触发;文本事件:当在文本中输入文本时触发;合成事宜:当为IME(Input Method Editor,输入法编辑器)输入字符时触发;

HTML5规范也定义了大量的事宜:历史管理、拖放、跨文本通信,以及多媒体等事宜;

除了这些事宜,有些浏览器会在DOM和BOM中也实现其他专有事宜;

从其余一个角度来分,事宜大致可以分成几大类:

依赖于设备的输入型事宜:这些事宜依赖于特定的输入设备,比如鼠标和键盘,也包括触摸事宜;例如,mousedown、mousemove之类的,只能通过鼠标设备,而keydown或keypress只能通过键盘设备,touchmove或gesturechange也只能通过触摸设备实现;

独立于设备的输入型事宜:不依赖于特定的输入设备,比如click事宜,既可以通过鼠标单击实现,也可以通过键盘或触摸设备实现;再如textinput事宜,即可以通过键盘按键实现,也可以在剪切和粘贴实现,乃至通过手写设备来实现;

用户界面事宜:常日指的是一些注册在表单控件上的事宜,例如文本框获取焦点的focus事宜,控件改变值的change事宜或提交表单的submit事宜;

状态变革事宜:表示某些生命周期或干系状态的变革的事宜,比如,文档加载的load事宜或DOMContentLoaded事宜或文档状态readystatechange事宜;再如HTML5的历史管理的popstate事宜,online或offline事宜;

特定API事宜:HTML5及干系的规范中定义的事宜,例如:拖放事宜,多媒体的干系事宜;

UIEvent事宜:

UIEvent事宜表示大略的用户界面事宜,但包含一些不一定与用户操作有关的事宜,紧张与元素的焦点有关;

该事宜类继续自Event类;由其也派生出其他子类,如MouseEvent、TouchEvent、FocusEvent、KeyboradEvent、WheelEvent、InputEvent和CompositionEvent;

其自身定义了一些属性,如:detail、layerX、layerY、pageX、pageY、sourceCapabilities、view和which;

UIEvent干系的事宜:

DOMActive:表示元素已经被用户操作(通过鼠标或键盘)激活时发生;load:当页面完备加载后在window上触发,当所有框架都加载完毕时在框架集上触发,当图像加载完毕时在<img>元素上触发,或者当嵌入的内容加载完成时在<object>元素上触发;unload:当页面完备卸载后在window上触发,当所有框架都卸载后在框架集上触发,或者当嵌入的内容卸载完毕后在<object>元素上面触发;abort:当用户停滞下载过程时,如果嵌入的内容没有加载完,则在<object>元素上触发;error:当发生Javascript缺点时在window上触发,当无法加载图像时在<img>元素上面触发,当无法加载嵌入内容时在<object>元素上触发,或者当一或多个框架无法加载时在框架集上触发;select:当用户选择文本框(<input>或<textarea>)中的一或多个字符时触发;resize:当窗口或框架的大小变革时在window或框架上触发;scroll:当用户滚动带滚动条的元素中的内容时,在该元素上触发;

以上这些事宜,在DOM2级事宜中,除了DOMActive之外,其他事宜都属于HTML事宜,以是,在确定浏览器是否支持DOM2级事宜,末了检测一下,如:

var isSupported = document.implementation.hasFeature(&#34;HTMLEvents","2.0");

确定浏览器是否支持DOM3级事宜,如:

var isSupported = document.implementation.hasFeature("UIEvent","3.0");

其余,这些事宜,多数与window工具或表单控件干系,以是有些地方把这些事宜也称为window事宜,便是由于这些事宜的发生多数与浏览器窗口有关;

load加载事宜:当页面完备加载后(包括所有图像、Javascript文件和CSS文件等外部资源),就会触发window工具的load事宜,这也是Javascript中最常利用的事宜;

有两种定义onload事宜处理程序的办法:

window.addEventListener("load", function(event){ console.log("Loaded"); console.log(event); // Event},false);// 或在IE10以下window.attachEvent("onload", function(event){ console.log("Loaded"); console.log(window.event);});

为<body>元素添加onload特性;

<body onload="console.log(event);">

一样平常来说,在window上发生的任何事宜都可以在<body>元素中通过相应的特性来指定,由于在HTML中无法访问window元素;

图像也可以触发load事宜,无论是在DOM中的图像还是在HTML中的图像元素;

<img src="images/1.jpg" onload="alert('图片已加载')" />

或:

var img = document.querySelector("img");img.addEventListener("load", function(event){ console.log(event.target.src);});// 或EventUtil.addHandler(img, "load", function(event){ event = EventUtil.getEvent(event); console.log(EventUtil.getTarget(event).src);});

在创建新的<img>元素时,可以为其指定一个事宜处理程序,只须要指定src属性就可以下载,并不须要添加到DOM树中,如:

window.addEventListener("load", function(event){ var img = document.createElement("img"); img.addEventListener("load", function(e){ console.log(e.target.src); }); img.src = "images/1.jpg"; document.body.appendChild(img);});// 或者EventUtil.addHandler(window, "load", function(){ var img = document.createElement("img"); EventUtil.addHandler(img, "load", function(event){ event = EventUtil.getEvent(event); console.log(EventUtil.getTarget(event).src); }); img.src = "images/1.jpg"; document.body.appendChild(img);});

还可以利用DOM0级的Image工具实现,如:

// 把 var img = document.createElement("img"); // 换成 var img = new Image();

还有一些元素也以非标准的办法支持load事宜;在标准浏览器中,<script>元素也会触发load事宜,以确定动态加载的js文件是否加载完毕,在设置了<script>的scr属性并且添加到文档中,才会开始下载;

window.addEventListener("load", function(){ var script = document.createElement("script"); script.addEventListener("load", function(event){ console.log(event.target.src); }); script.src = "scripts/main.js"; document.getElementsByTagName("head")[0].appendChild(script);});// 或EventUtil.addHandler(window, "load", function(){ var script = document.createElement("script"); EventUtil.addHandler(script, "load", function(event){ console.log(event); var target = EventUtil.getTarget(event); console.log(target.src); }); script.src = "scripts/main.js"; document.getElementsByTagName("head")[0].appendChild(script);});

此时,event工具的target及currentTarget或srcElement引用都是<script>节点;

IE8及以下浏览器不支持<script>元素上的load事宜,但以上代码不会抛出非常;

浏览器还支持<link>元素上的load事宜,如:

window.addEventListener("load", function(){ var link = document.createElement("link"); link.rel = "stylesheet"; link.addEventListener("load", function(event){ console.log(event.target.href); }); link.href = "styles/css.css"; document.getElementsByTagName("head")[0].appendChild(link);});

与<script>类似,指定其href属性并且添加到文档中才会下载;

unload事宜:在页面被完备卸载后触发;或者从一个页面切换到另一个页面,或者刷新操作也会触发unload事宜,如:

<body onunload="alert('unload');">

抛出非常:blocked alert during unload,也便是页面被壅塞了,而在unload事宜处理中,是不许可壅塞的,诸如弹窗之类的,都会引起壅塞;精确的做法:

<body onunload="console.log('unload');">

或:

EventUtil.addHandler(window, "unload", function(event){ console.log("unload");});unload事宜特点:unload事宜的event工具只包含target(或srcElement)属性,且值为document;unload事宜发生时的状态该当是:所有资源仍存在 (图片, iframe 等.)对付终端用户所有资源均不可见;界面交互无效 (window.open, alert, confirm 等,会引起壅塞);缺点不会停滞卸载文档的过程;

unload事宜实行韶光很短,并且是在统统都被卸载之后才触发,以是不适宜处理常规代码,一样平常是取消(或打消)该页面上的工具引用,以避免内存泄露;

var obj = {name:"wangwei",age:18};window.addEventListener("unload", function(event){ var oDiv = document.getElementById("mydiv"); console.log(oDiv); var img = document.getElementsByTagName("img")[0]; console.log(img); console.log(obj); obj = null;console.log(obj);debugger;});var obj = {name:"wangwei",age:18};window.addEventListener("unload", function(event){ localStorage.setItem("unload","页面被unload了"); localStorage.setItem("person", obj);});

示例:统计一个页面勾留的时长,如:

window.addEventListener("load", function(){ var start = new Date(); console.log(start); window.addEventListener("unload", function(){ var end = new Date(); var duration = (end.getTime() - start.getTime()) / 1000; var pageView = { pageStayTime: duration, pageUrl: location.href }; console.log("保存到数据库中"); });});

其余,unload事宜是不冒泡的,也是不可取消的;

同样,DOM2级事宜规定该当在<body>元素而非window工具上触发unload事宜,但所有浏览器都在window上实现了unload事宜;

error事宜:window.onerror属性看起来像事宜处理程序,并且当Javascript出错时就会触发它,但是,它并不是真正的事宜处理程序,由于它的参数不是event工具,而是5个参数,由这5个参数可以获取详细的缺点信息;

message:缺点信息,描述缺点的一条;URL:引发缺点的Javascript所在的文档的URL;line:文档中发生缺点的行数;column:发生缺点的列数;error:缺点工具,这个error也称为全局缺点工具;

window.onerror = function(sMessage, sUrl, sLine, sColumn, error){console.log("Error:" + sMessage + " URL:" + sUrl + " Line:" + sLine + " Column:" + sColumn);console.log(error); return true;}

但如果利用DOM2级事宜处理程序,个中的参数便是event工具;

window.onload = function(){ num1 + num2;}window.addEventListener("error", function(event){console.log(event); // ErrorEvent return true;});

ErrorEvent类继续自Event类,其定义了如下属性:

message:只读,返回包含了所发生缺点的描述信息;filename:只读,包含了发生缺点的脚本文本的URL;lineno:只读,缺点发生的行号;colon:只读,缺点发生的列号;error:只读,发生缺点时所抛出的Error工具;

这5个属性也对应着window.onerror属性的5个参数;

如果是图片的onerror事宜,便是一个真正的事宜,个中只有一个参数,便是一个event工具;

var img = document.getElementsByTagName("img")[0];img.onerror = function(event){ console.log(event); // Event type为error}

abort事宜:当一个资源的加载已中止时,将触发该事宜;

var video = document.querySelector("video");videoSrc = "https://www.zeronetwork.cn/video.webm";video.addEventListener("abort", function(event){ console.log(event); console.log("下载中止:" + videoSrc);});var source = document.createElement("source"); source.setAttribute("src", videoSrc); source.setAttribute("type", "video/webm"); video.appendChild(source);source.addEventListener("error", function(event){ console.log(event); return true;});

resize事宜:当浏览器窗口的大小被调度,就触发resize事宜,该事宜在window上触发;

EventUtil.addHandler(window, "resize", function(event){ console.log(event);});

在标准浏览器中,event工具有target属性,且值为window工具,但IE未供应任何属性;

浏览器的大小改变1像素就会触发resize事宜,然后再随着变革不断重复触发;

最大化或最小化窗口时,也会触发resize事宜;但是部分浏览器会在最大化或最小化时触发两次或以上的该事宜,此时可以利用setTimeout()办理,也便是延迟实行某些代码,如:

function callBack(){ console.log("callBack");}window.addEventListener("resize", function(event){ var target = this; if(target.resizeFlag) clearTimeout(target.resizeFlag); target.resizeFlag = setTimeout(function(){ callBack(); console.log("resize"); target.resizeFlag = null; },200);});

示例:随窗口大小的变革而变革,如:

var mydiv = document.getElementById("mydiv");var w = mydiv.clientWidth, h = mydiv.clientHeight, dx = w / h, dw = document.documentElement.clientWidth, scale = w / dw;window.addEventListener("resize", function(event){ var dw = document.documentElement.clientWidth; mydiv.style.width = dw scale + "px"; var w = mydiv.clientWidth; mydiv.style.height = w dx scale + "px"; console.log(mydiv.style.width); console.log(mydiv.style.height);});

示例:

<style>{margin:0;padding:0;}.leftDiv,.rightDiv{ width: 40%; overflow-y: scroll; float: left; margin-right: 10px; background-color: purple;}</style><div class="leftDiv">leftDiv ...</div><div class="rightDiv">rightDiv ...</div><script>var leftDiv, rightDiv, dHeight;window.addEventListener("load", function(){ leftDiv = document.querySelector(".leftDiv"); rightDiv = document.querySelector(".rightDiv"); dHeight = document.documentElement.clientHeight; leftDiv.style.height = dHeight + "px"; rightDiv.style.height = dHeight + "px";});window.addEventListener("resize", function(event){ dHeight = document.documentElement.clientHeight; leftDiv.style.height = dHeight + "px"; rightDiv.style.height = dHeight + "px";});</script>

resize事宜目前只能注册在window工具上,它不支持注册在DOM元素上,如果要监听DOM元素的resize事宜,最好的方案便是利用自定义事宜;

scroll事宜:虽然是在window工具上发生,但它实际表示的是页面中相应元素的变革;即可以在滚动窗口或其他元素时,跟踪变革来确保某些内容一贯在屏幕上可见;

window.addEventListener("scroll", function(event){ console.log(event); // Event});

该事宜工具并没有供应滚动干系的信息,只是一个普通的Event的工具;

在殽杂模式下,可以通过<body>元素的scrollLeft和scrollTop来监控到这一变革;在标准模式下,会通过<html>元向来反响这一变革;

window.onscroll = function(){ console.log("x:" + document.documentElement.scrollLeft + ", y:" + document.documentElement.scrollTop);}// 或window.addEventListener("scroll", function(event){ if(document.compatMode == "CSS1Compat") console.log(document.documentElement.scrollTop); else console.log(document.body.scrollTop);});

与resize事宜类似,scroll事宜会在文档被滚动活动期间会被重复触发,因此在scroll事宜处理程序中只管即便保持大略的代码;

scroll事宜示例:

<div id="mydiv" style="width:200px;height:200px;background-color: purple; position: absolute;top:50px;right:50px;"></div><div style="height: 2000px; background-color:lightgreen;"></div><script>window.onscroll = function(){ var oDiv = document.getElementById("mydiv"); oDiv.style.top = document.documentElement.scrollTop + "px";}</script>

scroll事宜也可以注册到Element元素上;如:

var oDiv = document.getElementById("mydiv");console.log(oDiv.scrollHeight);oDiv.addEventListener("scroll", function(event){ // console.log(event); // Event console.log(event.target.scrollTop);});

事宜防抖(debounce)和节流(throttle):

防止事宜被频繁触发;干系的事宜有:mousemove、keydown、keypress、keyup、resize、scroll等;

防抖:触发高频事宜后n秒内函数只实行一次,如果n秒内高频事宜再次触发,则重新打算韶光;如:

var timer = null; // 创建一个标记用来存放定时器的返回值window.addEventListener("resize", function(){ if(timer){ clearTimeout(timer); // 每当resize时把之前的一个setTimeout打消 timer = null; } if(!timer){ timer = setTimeout(function(){ // 再创建一个新的定时器 console.log("防抖"); },500); }});

在事宜防抖中,打消定时器的机遇很关键,必须在新定时器天生之前,如果在之后,会将所有定时器都打消,目标函数一次都不实行;或:

function debounce(callback, delay){ var timeout = 0; return function(){ var arg = arguments; // 一贯触发,就一贯打消 clearTimeout(timeout); // 直到事宜不再触发,末了一个定时器没有打消,delay后就会实行定时器, // 如此,就确保只实行一次 timeout = setTimeout(function(){ callback.apply(this, arg); }, delay); };}function fn(e){ console.log("fn" + e);}window.addEventListener("resize", debounce(fn, 500));

示例:输入框验证

function checkEmail(callback,delay){ var t = null; return function(){ var arg = arguments; clearTimeout(t); t = setTimeout(function(){ callback.apply(this, arg); }, delay); }}function emailHander(e){ var reg = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; if(!reg.test(e.target.value)){ e.target.style.backgroundColor = "red"; setTimeout(function(){ e.target.style.backgroundColor = ""; },800); console.log("格式禁绝确"); }else{ e.target.style.backgroundColor = "green"; console.log("精确"); }}var email = document.getElementById("email");email.addEventListener("keyup", checkEmail(emailHander,800), false);

节流:防抖是多次触发事宜,目标函数只实行一次,不管触发这些事宜用了多少韶光;而节流是在一定韶光内只会实行一次,稀释函数的实行频率,进而达到缓慢实行目标函数的目的;如:

利用setTimeout():

var timeoutId;window.addEventListener("resize", function(event){ if(!timeoutId){ timeoutId = setTimeout(function(){ console.log("延迟实行"); // 只实行一次 clearTimeout(timeoutId); // timeoutId = null; // 换成这一句,500ms实行一次 },500); }});// 或function resizeHandler(event){ // 先解除绑定 window.removeEventListener("resize", resizeHandler); console.log(document.documentElement.clientWidth); // 重新绑定 setTimeout(function(){ window.addEventListener("resize", resizeHandler); },500);}window.addEventListener("resize", resizeHandler);

利用setInterval():

将事宜处理程序放在setInterval()函数中,每隔一段韶光,去监测一次是否发生了scroll事宜,然后实行,而scroll事宜只是改变scrolled的值,不会影响性能,如:

var scrolled = false;window.addEventListener("scroll", function(){ scrolled = true;});setInterval(function(){ if(scrolled){ // 代码处理 console.log("scroll"); scrolled = false; }},500);

利用韶光戳:

var startTime = new Date();var flag = false;var delay = 200;window.addEventListener("resize", function(){ startTime = new Date(); if(flag === false){ flag = true; setTimeout(resizeEnd, delay); }});function resizeEnd(){ if(new Date() - startTime <= delay) setTimeout(resizeEnd, delay); else{ flag = false; console.log(document.documentElement.clientWidth); }}

或:

function thorttle(callback, delay){ var timeout = 0; var now = new Date() - 0; return function(){ var arg = arguments; var last = new Date() - 0; clearTimeout(timeout); if(last - now >= delay){ now = last; // 将上次实行的韶光赋值给now }else{ // 目标函数在这里实行 timeout = setTimeout(function(){ callback.apply(this, arg); }, delay); } };}function fn(e){ console.log("节流" + e);}window.addEventListener("resize", thorttle(fn, 500));

利用开关:

设置一个开关,一次只能有一个触发实行,并对实行设置计时一段韶光再实行,实行完毕之后再解锁;如:滚动事宜;

function loadMore(){ var canRun = true; return function(){ if(!canRun) return; canRun = false; setTimeout(function(){ var docHeight = document.documentElement.offsetHeight; // 文档高度 var winHeight = window.innerHeight; // 窗口高度 var scrollDistance = document.documentElement.scrollTop; // 滚动间隔 // 当滚动到底部时 if(docHeight - (winHeight + scrollDistance) <= 100){ console.log("Loading..."); } canRun = true; },600); }}window.addEventListener("scroll", loadMore());

两者比较:

节流在某个韶光段内,目标函数能实行一次,限定目标函数的实行频率,不管事宜触发了多少次;

防抖是多次触发事宜,目标函数只实行一次,不管触发了这些事宜用了多少韶光;

节流函数限定目标函数的实行频率,有连续变革的效果,适用于关注变革过程的操作,可以调度目标函数实行频率使得变革更加平滑,比如动画、改变窗口时实行某些操作等,常用事宜resize、scroll、mouseWheel、touchmove、mouseover等;

防抖函数适用于更关注结果的操作,不太关注操作过程,常见的事宜有 input、keyup等;

FocusEvent焦点事宜:

焦点事宜会在页面元素得到或失落去焦点时触发,或某些工具调用了focus()和blur()方法也会触发该事宜;利用这些事宜并与document.hasFocus()方法及document.activeElement属性合营,可以知晓用户在页面上的行踪;

有以下6个焦点事宜:

blur:在元素失落去焦点时触发,该事宜不会冒泡;focus:在元素得到焦点时触发,该事宜不会冒泡;DOMFocusIn:在元素得到焦点时触发,该事宜与HTML事宜focus等价,但它冒泡;DOM3级事宜废弃了它,应利用focusin;FF及低版本的IE不支持;DOMFocusOut:在元素失落去焦点时触发,该事宜是HTML事宜blur等价,但它冒泡;DOM3级事宜废弃了它,应利用focusout;FF及低版本的IE不支持;focusin:在元素得到焦点时触发,该事宜与HTML事宜focus等价,但它冒泡;focusout:在元素失落去焦点时触发,该事宜是HTML事宜blur等价,但它冒泡;

要确定浏览器是否支持这些事宜,可以检测:

var isSupported = document.implementation.hasFeature("FocusEvent", "3.0");

可以得到焦点事宜的元素一样平常指的是window或表单控件或是超链接或是可编辑元素,称为focusable元素;但在IE中普通元素也可以得到焦点;

window.onblur = function(){ document.title = "你离开了";};window.onfocus = function(){ document.title = "你来了";};var oDiv = document.getElementById("mydiv");oDiv.contentEditable = true;// oDiv.tabIndex = 1; // 或者添加tabIndex属性也可以oDiv.focus();console.log(document.activeElement);oDiv.addEventListener("focus", function(event){ console.log(event.target.id);});

这一类事宜中最紧张的两个是focus和blur,它们都是Javascript早期就得到所有浏览器都支持的事宜,这两个事宜的最大问题是它们不冒泡,因此,才涌现了IE的focusin和focusout与Opera的DOMFocusIn和DOMFocusOut这两对事宜,后来IE的办法被DOM3级事宜纳为标准办法;

var btn = document.getElementById("btn");btn.addEventListener("focus", function(event){ console.log(event); // FocusEvent});

FocusEvent类:

表示和焦点干系的事宜类,其继续自UIEvent类;

其自身只添加了一个属性relatedTarget,代表这次事宜的干系目标,但在实用中,例如切换浏览器tab标签时,为了安全起见,所有浏览器都会返回null;

当焦点从页面中的一个元素移动到另一个元素,会依次触发下列事宜:

blur在失落去焦点的元素上触发、focusout在失落去焦点的元素上触发、DOMFocusOut在失落去焦点的元素上触发、focus在得到焦点的元素上触发、focusin在得到焦点的元素上触发、DOMFocusIn在得到焦点的元素上触发;但IE不遵照这次序;

function handler(event){ console.log(event.target.id + ":" + event.type);}var btn = document.getElementById("btn");btn.addEventListener("DOMFocusIn", handler, false);btn.addEventListener("DOMFocusOut", handler, false);btn.addEventListener("focus", handler, false);btn.addEventListener("blur", handler, false);btn.addEventListener("focusin", handler, false);btn.addEventListener("focusout", handler, false);btn.focus();var txt = document.getElementById("txt");txt.addEventListener("focus", handler, false);txt.addEventListener("blur", handler, false);txt.addEventListener("DOMFocusIn", handler, false);txt.addEventListener("DOMFocusOut", handler, false);txt.addEventListener("focusin", handler, false);txt.addEventListener("focusout", handler, false);

个中,blur、DOMFocusOut和focusout的事宜目标是失落去焦点的元素,而focus、DOMFocusIn和focusin的事宜目标是得到焦点的元素;

其余,如果同时注册了focusin和DOMFocusIn或focusout和DOMFocusOut,在IE中只会触发focusin和focusout;

其余,除了focus和blur事宜,其他事宜只能通过DOM2级事宜添加,如:

var btn = document.getElementById("btn");btn.onfocusin = function(event){ console.log(event); // 不会触发};btn.onDOMFocusIn = function(event){ console.log(event); // 不会触发,IE会触发};

onfocusin和onfocusout事宜,在HTML事宜处理中,除FF,其它都支持;DOMFocusIn和DOMFocusOut,在HTML事宜处理中,都不支持;

小运用:改变文本框样式,如:

<style> .focusInput{border:1px solid purple;outline: none; background-color: rgba(0, 0, 0, .6);}</style><script>function focusInput(focusClass){ var elements = document.getElementsByTagName("input"); for(var i=0,len=elements.length; i<len; i++){ var elt = elements[i]; if(elt.type == "text"){ elt.onfocus = function(){ this.className = focusClass; }; elt.onblur = function(){ this.className = ""; } } }}window.onload = function(){ focusInput('focusInput');}</script>

focusin和focusout事宜是冒泡的,因此可以利用事宜代理,如:

<form id="myform" action="demo.jsp"><input type="text" id="firstname" value="firstname" /> <input type="text" id="lastname" value="lastname" /> </form><script>var myform = document.getElementById("myform");myform.addEventListener("focusin", function(event){ event.target.className = "focused";});myform.addEventListener("focusout", function(event){ event.target.className = "";});</script>

示例:验证数据,如:

<style> .invalid{border-color:red;} #error{color:red}</style><p>邮箱:<input type="email" id="email" /></p><div id="error"></div><script>var email = document.getElementById("email");var error = document.getElementById("error");email.addEventListener("blur", function(event){ if(!event.target.value.includes("@")){ event.target.classList.add("invalid"); error.innerHTML = "请输入精确的邮箱"; }});email.addEventListener("focus", function(event){ if(this.classList.contains("invalid")){ this.classList.remove("invalid"); error.innerHTML = ""; }});</script>

或者利用focus()和blur()方法,如:

<style> .error{background-color: red !important;}</style><p>邮箱:<input type="email" id="email" /></p><script>var email = document.getElementById("email");email.addEventListener("blur", function(event){ if(!event.target.value.includes("@")){ event.target.classList.add("error"); event.target.focus(); }else event.target.classList.remove("error");});</script>

示例:一个HTML编辑器;

<style>.container,.editor{width:400px; height: 150px; display: block;}.container{padding: 2px; border:1px solid;}.editor{padding: 0; border:2px solid blue;}.editor:focus{outline: none;}</style><div id="container" class="container"> <h1>Web前端开拓</h1></div><script>var area = null;var container = document.getElementById("container");container.addEventListener("click", function(event){ editStart();},false);function editStart(){ area = document.createElement("textarea"); area.className = "editor"; area.value = container.innerHTML; area.addEventListener("keydown", function(event){ if(event.keyCode == 13) this.blur(); },false); area.addEventListener("blur", function(event){ editEnd(); }); container.replaceWith(area); area.focus();}function editEnd(){ container.innerHTML = area.value; area.replaceWith(container);}</script>

当用户按下Enter键或失落去焦点时,<textarea>变回<div>,其内容在<div>中变为HTML;