input事件当<input>、<textarea>的值发生变化时触发。此外,打开contenteditable属性的元素,只要值发生变化,也会触发input事件。input事件的一个特点,就是会连续触发,比如用户每次按下一次按键,就会触发一次input事件。select事件当在<input>、<textarea>中选中文本时触发。Change事件当<input>、<select>、<textarea>的值发生变化时触发。它与input事件的最大不同,就是不会连续触发,只有当全部修改完成时才会触发,而且input事件必然会引发change事件。具体来说,分成以下几种情况。激活单选框(radio)或复选框(checkbox)时触发。用户提交时触发。比如,从下列列表(select)完成选择,在日期或文件输入框完成选择。当文本框或textarea元素的值发生改变,并且丧失焦点时触发。reset事件当表单重置(所有表单成员变回默认值)时由form元素触发。
submit事件当表单数据向服务器提交时由form元素触发。
以下事件与网页的加载与卸载相关:beforeunload事件当窗口将要关闭,或者document和网页资源将要卸载时触发。它可以用来防止用户不当心关闭网页。该事件的默认动作就是关闭当前窗口或文档。如果在监听函数中,调用了event.preventDefault(),或者对事件对象的returnValue属性赋予一个非空的值,就会自动跳出一个确认框,让用户确认是否关闭网页。如果用户点击“取消”按钮,网页就不会关闭。监听函数所返回的字符串,会显示在确认对话框之中
window.addEventListener('beforeunload', function( event ) {event.returnValue = '你确认要离开吗?';//或event.preventDefault();});unload事件在窗口关闭或者document对象将要卸载时触发,发生在window、body、frameset等对象上面。它的触发顺序排在beforeunload、pagehide事件后面。unload事件只在页面没有被浏览器缓存时才会触发,换言之,如果通过按下“前进/后退”导致页面卸载,并不会触发unload事件。当unload事件发生时,document对象处于一个特殊状态。所有资源依然存在,但是对用户来说都不可见,UI互动(window.open、alert、confirm方法等)全部无效。这时即使抛出错误,也不能停止文档的卸载。
load事件在页面加载成功时触发,error事件在页面加载失败时触发。注意,页面从浏览器缓存加载,并不会触发load事件。这两个事件实际上属于进度事件,不仅发生在document对象,还发生在各种外部资源上面。浏览网页就是一个加载各种资源的过程,图像(image)、样式表(style sheet)、脚本(script)、视频(video)、音频(audio)、Ajax请求(XMLHttpRequest)等等。这些资源和document对象、window对象、XMLHttpRequestUpload对象,都会触发load事件和error事件。
pageshow事件,pagehide事件:默认情况下,浏览器会在当前会话(session)缓存页面,当用户点击“前进/后退”按钮时,浏览器就会从缓存中加载页面。
pageshow事件在页面加载时触发,包括第一次加载和从缓存加载两种情况。如果要指定页面每次加载(不管是不是从浏览器缓存)时都运行的代码,可以放在这个事件的监听函数。第一次加载时,它的触发顺序排在load事件后面。从缓存加载时,load事件不会触发,因为网页在缓存中的样子通常是load事件的监听函数运行后的样子,所以不必重复执行。同理,如果是从缓存中加载页面,网页内初始化的JavaScript脚本(比如DOMContentLoaded事件的监听函数)也不会执行。pageshow事件有一个persisted属性,返回一个布尔值。页面第一次加载时,这个属性是false;当页面从缓存加载时,这个属性是true。if (event.persisted){...}
pagehide事件与pageshow事件类似,当用户通过“前进/后退”按钮,离开当前页面时触发。它与unload事件的区别在于,如果在window对象上定义unload事件的监听函数之后,页面不会保存在缓存中,而使用pagehide事件,页面会保存在缓存中。pagehide事件的event对象有一个persisted属性,将这个属性设为true,就表示页面要保存在缓存中;设为false,表示网页不保存在缓存中,这时如果设置了unload事件的监听函数,该函数将在pagehide事件后立即运行。如果页面包含frame或iframe元素,则frame页面的pageshow事件和pagehide事件,都会在主页面之前触发。
以下事件与文档状态相关:
DOMContentLoaded事件当HTML文档下载并解析完成以后,就会在document对象上触发DOMContentLoaded事件。这时,仅仅完成了HTML文档的解析(整张页面的DOM生成),所有外部资源(样式表、脚本、iframe等等)可能还没有下载结束。也就是说,这个事件比load事件,发生时间早得多。注意,网页的JavaScript脚本是同步执行的,所以定义DOMContentLoaded事件的监听函数,应该放在所有脚本的最前面。否则脚本一旦发生堵塞,将推迟触发DOMContentLoaded事件。IE8不支持DOMContentLoaded,可以使用readystatechange事件,在低版本的IE中代替DOMContentLoaded事件。
readystatechange事件发生在Document对象和XMLHttpRequest对象,当它们的readyState属性发生变化时触发。
以下事件与窗口行为有关:
scroll事件在文档或文档元素滚动时触发,主要出现在用户拖动滚动条。由于该事件会连续地大量触发,所以它的监听函数之中不应该有非常耗费计算的操作。推荐的做法是使用requestAnimationFrame或setTimeout或使用自定义的throttle函数(节流函数)控制该事件的触发频率,然后可以结合customEvent抛出一个新事件(CustomEvent(type,eventInit) 创建一个自定义事件)
resize事件在改变浏览器窗口大小时触发,发生在window、body、frameset对象上面。该事件也会连续地大量触发,所以最好像上面的scroll事件一样,通过throttle函数控制事件触发频率
以下事件与文档的URL变化相关:
hashchange事件在URL的hash部分(即#号后面的部分,包括#号)发生变化时触发。如果老式浏览器不支持该属性,可以通过定期检查location.hash属性,模拟该事件,hashchange事件对象除了继承Event对象,还有oldURL属性和newURL属性,分别表示变化前后的URL
popstate事件在浏览器的history对象的当前记录发生显式切换时触发。注意,调用history.pushState()或history.replaceState(),并不会触发popstate事件。该事件只在用户在history记录之间显式切换时触发,比如鼠标点击“后退/前进”按钮,或者在脚本中调用history.back()、history.forward()、history.go()时触发。该事件对象有一个state属性,保存history.pushState方法和history.replaceState方法为当前记录添加的state对象。
以下三个事件属于文本操作触发的事件
cut事件:在将选中的内容从文档中移除,加入剪贴板后触发。
copy事件:在选中的内容加入剪贴板后触发。
paste事件:在剪贴板内容被粘贴到文档后触发。
这三个事件都有一个clipboardData只读属性。该属性存放剪贴的数据,是一个DataTransfer对象,具体的API接口和操作方法,请参见‘触摸事件’的DataTransfer对象
焦点事件:
发生在Element节点和document对象上面,与获得或失去焦点相关。它主要包括以下四个事件。
focus事件:Element节点获得焦点后触发,该事件不会冒泡。
blur事件:Element节点失去焦点后触发,该事件不会冒泡。
focusin事件:Element节点将要获得焦点时触发,发生在focus事件之前。该事件会冒泡。Firefox不支持该事件。
focusout事件:Element节点将要失去焦点时触发,发生在blur事件之前。该事件会冒泡。Firefox不支持该事件。
这四个事件的事件对象,带有target属性(返回事件的目标节点)和relatedTarget属性(返回一个Element节点)。对于focusin事件,relatedTarget属性表示失去焦点的节点;对于focusout事件,表示将要接受焦点的节点;对于focus和blur事件,该属性返回null。
由于focus和blur事件不会冒泡,只能在捕获阶段触发,所以addEventListener方法的第三个参数需要设为true。
lengthComputable:返回一个布尔值,表示当前进度是否具有可计算的长度。如果为false,就表示当前进度无法测量。
total:返回一个数值,表示当前进度的总长度。如果是通过HTTP下载某个资源,表示内容本身的长度,不含HTTP头部的长度。如果lengthComputable属性为false,则total属性就无法取得正确的值。
loaded:返回一个数值,表示当前进度已经完成的数量。该属性除以total属性,就可以得到目前进度的百分比。if (e.lengthComputable) {var percentComplete = e.loaded / e.total; }
包含以下事件:
abort事件:当进度事件被中止时触发。如果发生错误,导致进程中止,不会触发该事件。
error事件:由于错误导致资源无法加载时触发,不会冒泡。error事件的监听函数最好放在如img元素的HTML属性中,这样才能保证发生加载错误时百分之百会执行。
load事件:进度成功结束时触发。
loadstart事件:进度开始时触发。
loadend事件:进度停止时触发,发生顺序排在error事件\abort事件\load事件后面。loadend事件的监听函数可以用来取代abort事件/load事件/error事件的监听函数,loadend事件本身不提供关于进度结束的原因,但可以用它来做所有进度结束场景都需要做的一些操作。
progress事件:当操作处于进度之中,由传输的数据块不断触发。
drag事件:拖拉过程中,在被拖拉的节点上持续触发。dragstart事件:拖拉开始时在被拖拉的节点上触发,该事件的target属性是被拖拉的节点。通常应该在这个事件的监听函数中,指定拖拉的数据。dragend事件:拖拉结束时(释放鼠标键或按下escape键)在被拖拉的节点上触发,该事件的target属性是被拖拉的节点。它与dragStart事件,在同一个节点上触发。不管拖拉是否跨窗口,或者中途被取消,dragend事件总是会触发的。dragenter事件:拖拉进入当前节点时,在当前节点上触发,该事件的target属性是当前节点。通常应该在这个事件的监听函数中,指定是否允许在当前节点放下(drop)拖拉的数据。如果当前节点没有该事件的监听函数,或者监听函数不执行任何操作,就意味着不允许在当前节点放下数据。在视觉上显示拖拉进入当前节点,也是在这个事件的监听函数中设置。dragover事件:拖拉到当前节点上方时,在当前节点上持续触发,该事件的target属性是当前节点。该事件与dragenter事件基本类似,默认会重置当前的拖拉事件的效果(DataTransfer对象的dropEffect属性)为none,即不允许放下被拖拉的节点,所以如果允许在当前节点drop数据,通常会使用preventDefault方法,取消重置拖拉效果为none。dragleave事件:拖拉离开当前节点范围时,在当前节点上触发,该事件的target属性是当前节点。在视觉上显示拖拉离开当前节点,就在这个事件的监听函数中设置。drop事件:被拖拉的节点或选中的文本,释放到目标节点时,在目标节点上触发。注意,如果当前节点不允许drop,即使在该节点上方松开鼠标键,也不会触发该事件。如果用户按下Escape键,取消这个操作,也不会触发该事件。该事件的监听函数负责取出拖拉数据,并进行相关处理。
关于拖拉事件,有以下几点注意事项:
1.拖拉过程只触发以上这些拖拉事件,尽管鼠标在移动,但是鼠标事件不会触发。2.将文件从操作系统拖拉进浏览器,不会触发dragStart和dragend事件。3.dragenter和dragover事件的监听函数,用来指定可以放下(drop)拖拉的数据。由于网页的大部分区域不适合作为drop的目标节点,所以这两个事件的默认设置为当前节点不允许drop。如果想要在目标节点上drop拖拉的数据,首先必须阻止这两个事件的默认行为,或者取消这两个事件。<div ondragover="return false">或<div ondragover="event.preventDefault()">
拖拉事件用一个DragEvent对象表示,该对象继承MouseEvent对象,DragEvent对象只有一个独有的属性DataTransfer,其他都是继承的属性。DataTransfer属性用来读写拖拉事件中传输的数据,所有的拖拉事件都有一个dataTransfer属性,用来保存需要传递的数据,这个属性的值是一个DataTransfer对象。拖拉的数据保存两方面的数据:数据的种类(又称格式)和数据的值。数据的种类是一个MIME字符串,比如 text/plain或者image/jpeg,数据的值是一个字符串;
dropEffect属性设置放下(drop)被拖拉节点时的效果,可能的值包括copy(复制被拖拉的节点)、move(移动被拖拉的节点)、link(创建指向被拖拉的节点的链接)、none(无法放下被拖拉的节点)。设置除此以外的值,都是无效的。effectAllowed属性设置本次拖拉中允许的效果,可能的值包括copy、move、link、copyLink、copyMove、linkMove、all、none、uninitialized(默认值,等同于all)。如果某种效果是不允许的,用户就无法在目标节点中达成这种效果。files属性是一个FileList对象,包含一组本地文件,可以用来在拖拉操作中传送。如果本次拖拉不涉及文件,则属性为空的FileList对象。通过files属性读取拖拉文件的信息。如果想要读取文件内容,就要使用FileReader对象。types属性是一个数组,保存每一次拖拉的数据格式,如‘text/uri-list’
setData方法用来设置事件所带有的指定类型的数据。它接受两个参数,第一个是数据类型,第二个是具体数据。如果指定的类型在现有数据中不存在,则该类型将写入types属性;如果已经存在,在该类型的现有数据将被替换。event.dataTransfer.setData("text/plain", "Text to drag");getData方法接受一个字符串(表示数据类型)作为参数,返回事件所带的指定类型的数据(通常是用setData方法添加的数据)。如果指定类型的数据不存在,则返回空字符串。event.dataTransfer.getData(types[0]);clearData方法接受一个字符串(表示数据类型)作为参数,删除事件所带的指定类型的数据。如果没有指定类型,则删除所有数据。如果指定类型不存在,则原数据不受影响。event.dataTransfer.clearData("text/uri-list");setDragImage可以用来自定义这张图片,它接受三个参数,第一个是img图片元素或者canvas元素,如果省略或为null则使用被拖动的节点的外观,第二个和第三个参数为鼠标相对于该图片左上角的横坐标和右坐标。event.dataTransfer.setDragImage(img, 0, 0);
identifier属性表示Touch实例的独一无二的识别符。它在整个触摸过程中保持不变。var id = touchItem.identifier;screenX属性和screenY属性,分别表示触摸点相对于屏幕左上角的横坐标和纵坐标,与页面是否滚动无关;clientX属性和clientY属性,分别表示触摸点相对于浏览器视口左上角的横坐标和纵坐标,与页面是否滚动无关pageX属性和pageY属性,分别表示触摸点相对于当前页面左上角的横坐标和纵坐标,包含了页面滚动带来的位移radiusX属性和radiusY属性,分别返回触摸点周围受到影响的椭圆范围的X轴和Y轴,单位为像素。rotationAngle属性表示触摸区域的椭圆的旋转角度,单位为度数,在0到90度之间。指尖接触屏幕,触摸范围会形成一个椭圆,这三个属性就用来描述这个椭圆区域。force属性返回一个0到1之间的数值,表示触摸压力。0代表没有压力,1代表硬件所能识别的最大压力。target属性返回一个Element节点,代表触摸发生的那个节点。当这个触点最开始被跟踪时(在 touchstart 事件中), 触点位于的HTML元素. 哪怕在触点移动过程中, 触点的位置已经离开了这个元素的有效交互区域, 或者这个元素已经被从文档中移除. 需要注意的是, 如果这个元素在触摸过程中被移除, 这个事件仍然会指向它, 但是不会再冒泡这个事件到 window 或 document 对象. 因此, 如果有元素在触摸过程中可能被移除, 最佳实践是将触摸事件的监听器绑定到这个元素本身, 防止元素被移除后, 无法再从它的上一级元素上侦测到从该元素冒泡的事件. 只读属性.
键盘相关属性altKey、ctrlKey、metaKey、shiftKey都为只读属性,返回一个布尔值,表示触摸的同时,是否按下某个键changedTouches属性返回一个TouchList对象,包含了由当前触摸事件引发的所有Touch对象(即相关的触摸点)。它包含了代表所有从上一次触摸事件到此次事件过程中,状态发生了改变的触点的 Touch 对象。只读属性。targetTouches属性返回一个TouchList对象,包含了触摸的目标Element节点内部,所有仍然处于活动状态的触摸点。touches属性返回一个TouchList对象,包含了所有当前接触触摸平面的触点的 Touch 对象,无论它们的起始于哪个 element 上,也无论它们状态是否发生了变化。只读属性type属性指此次触摸事件的类型。target属性此次触摸事件的目标 element 。这个目标元素对应 TouchEvent.changedTouches 中的触点的起始元素(在之后的事件类型中有说明),但是请注意:此次事件中其他的触点的起始元素可能有所不同。以防万一,应使用和每一个单独触点相关联的目标 。
touchstart:用户接触触摸屏时触发,它的target属性返回发生触摸的Element节点。touchend:用户不再接触触摸屏时(或者移出屏幕边缘时)触发,它的target属性与touchstart事件的target属性是一致的,它的changedTouches属性返回一个TouchList对象,包含所有不再触摸的触摸点(Touch对象)。touchmove:用户移动触摸点时触发,它的target属性与touchstart事件的target属性一致。如果触摸的半径、角度、力度发生变化,也会触发该事件。touchenter当触点进入某个 element 时触发。此事件没有冒泡过程。touchleave当触点离开某个 element 时触发。此事件没有冒泡过程。touchcancel:当触点由于某些原因被中断时触发。有几种可能的原因如下(具体的原因根据不同的设备和浏览器有所不同):1.由于某个事件取消了触摸:例如触摸过程被一个模态的弹出框打断。2.触点离开了文档窗口,而进入了浏览器的界面元素、插件或者其他外部内容区域。3.当用户产生的触点个数超过了设备支持的个数,从而导致 TouchList 中最早的 Touch 对象被取消。
function handleMove(evt) {evt.preventDefault(); // 阻止浏览器继续处理触摸事件,也阻止发出鼠标事件var touches = evt.changedTouches;for (var i = 0; i < touches.length; i++) {var id = touches[i].identifier;var touch = touches.identifiedTouch(id);console.log(touch.pageX, touch.pageY);}}
var event = new Event('build');elem.addEventListener('build', function (e) { ... }, false);elem.dispatchEvent(event);
var myEvent = new CustomEvent("myevent", {detail: {foo: "bar"},bubbles: true,cancelable: false});el.addEventListener('myevent', function(event) {console.log('Hello ' + event.detail.foo);});el.dispatchEvent(myEvent);
(function () {function CustomEvent ( event, params ) {params = params || { bubbles: false, cancelable: false, detail: undefined };var evt = document.createEvent( 'CustomEvent' );evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );return evt;}CustomEvent.prototype = window.Event.prototype;window.CustomEvent = CustomEvent;})();
function simulateClick() {var event = new MouseEvent('click', {'bubbles': true,'cancelable': true});var cb = document.getElementById('checkbox');cb.dispatchEvent(event);}
var event = document.createEvent('Event');event.initEvent('my-custom-event', true, true, {foo:'bar'});someElement.dispatchEvent(event);
event.initMouseEvent(type, canBubble, cancelable, view,detail, screenX, screenY, clientX, clientY,ctrlKey, altKey, shiftKey, metaKey,button, relatedTarget);
var simulateDivClick = document.createEvent('MouseEvents');simulateDivClick.initMouseEvent('click',true,true,document.defaultView,0,0,0,0,0,false,false,false,0,null,null);divElement.dispatchEvent(simulateDivClick);