event 事件2

4、事件类型

“DOM3级事件”规定了一下几类事件:

1)UI事件(用户界面事件),当用户与页面元素交互时触发

2)焦点事件,当元素获得或失去焦点时触发

3)鼠标事件,当用户通过鼠标在页面上执行操作时触发

4)滚动事件,当使用鼠标滚轮(或类似设备)时触发

5)文本事件,当在文档中输入文本时触发

6)键盘事件,当用户通过键盘在页面执行操作时触发

7)合成事件,当IME(Input Method Editor,输入法编辑器)输入字符时触发

8)变动事件(mutation),当底层DOM结构发生变化时触发

9)变动名称事件,当元素或属性名变动时触发。已废弃

 

4.1 UI事件

1)DOMActivate:表示元素已经被用户操作(通过鼠标或键盘)激活

2)load:当页面加载后在window上触发,当所有框架都加载完成时在框架集上触发,当图像加载完成时在<img>元素上触发,当嵌入的内容加载完成时在<object>元素上触发

3)unload:当页面完全卸载(页面关闭或刷新)后在window上触发,当所有框架都卸载后在框架集上触发,当嵌入内容卸载完后在<object>元素上触发

4)abort:在用户停止下载过程时,如果嵌入的内容没有加载完,则在<object>元素上触发

5)error:当发生JavaScript错误时在window上触发,当无法加载图像时在<img>元素上触发,当无法加载嵌入内容时在<object>元素上触发,当有一个或多个框架无法加载时在框架集上触发

6)select:当用户选择文本框(<input>或<textarea>)中的一个或多个字符时触发

7)resize:当窗口或框架的大小或变化是在window或框架上触发

8)scroll:当用户滚动带滚动条的元素是,在该元素上触发

 

var myimg = document.getElementById("myimg");
var mydiv = document.getElementById("mydiv");
EventUtil.addHandler(window,"load",function(event){
    var event = EventUtil.getEvent(event);
    console.log("event window Loaded, "+event.type);

    var image = new Image();
    EventUtil.addHandler(image,"load",function(event){  //预加载图片,Image 对象
        console.log("Image loaded");
        mydiv.appendChild(image);  // 图片加载完成后,插入DOM中
    });
    image.src = "img/IMAGE.png";  // 设置路径后就开始加载图片了


    var script = document.createElement("script");
    EventUtil.addHandler(script,"load",function () {  //IE9+、Firefox、Opera、Chrome、Safari3+,支持script元素的load事件
        console.log("script is loaded");
    });

    script.src = "js/test.js"; //对于script,只有在指定了src属性,并添加到文档后,才会开始加载script
    document.body.appendChild(script);

    var link = document.createElement("link");  // IE all、 FireFox、Chrome、Edge、Opera、Safari?,支持link元素的load事件
    link.type = "text/css";
    link.rel = "stylesheet";
    EventUtil.addHandler(link,"load",function (event) {
        console.log("link css loaded");
    });
    link.href = "css/list.css";
    document.getElementsByTagName("head")[0].appendChild(link);
});

function imgLoad(event){
    console.log("img loaded!");
    var event = EventUtil.getEvent(event);
    console.log(EventUtil.getTarget(event).src);
}
function imgLoadError(event){
    console.log("failed to load img!");
    var event = EventUtil.getEvent(event);
    console.log(EventUtil.getTarget(event).src);
}

//<img src="img/date.png" alt="user" id="myimg" onload="target = event.target ? event.target : event.srcElement; console.log('img loaded! ' + target.src)" onerror="console.log('failed to load img')"/>
EventUtil.addHandler(myimg, "load",imgLoad);// 在IE 上无法检测到图像的加载事件(估计是程序执行到这里,图片已经加载完了)
myimg.onload = imgLoad; // 在IE 上无法检测到图像的加载事件(估计是程序执行到这里,图片已经加载完了)

myimg.onerror = imgLoadError;

EventUtil.addHandler(window,"unload",function(event){ // unload事件多是用来清除引用,避免内存泄漏的

    console.log("unloaded!");// 页面已关闭,提示框看不到;刷新页面可以
});

EventUtil.addHandler(window,"resize",function(event){  // 页面调整高度或宽度触发,当拖放窗口大小时,会连续触发这个事件
    console.log('resized!');
});

EventUtil.addHandler(window,"scroll",function(event){  // 页面滚动时,会连续重复触发scroll事件
   if(document.compatMode == "CSS1Compat"){
       console.log(document.documentElement.scrollTop);
   } else {
       console.log(document.body.scrollTop);
   }
});

window 的 load、unload事件的event事件对象,在兼容DOM事件的浏览器里target是document,而不兼容DOM事件的浏览器(IE)中的srcElement没有值。另外, window 的 load、unload的事件处理程序都可以在<body>中指定 onload、onuload特性的方式添加

 

4.2 焦点事件

 1)focus:元素获得焦点时触发,这个事件不会冒泡,所有浏览器都支持

 2)blur:元素失去焦点时触发,这个事件不会冒泡,所有浏览器都支持

 3)focusin:元素获得焦点时触发,与 focus 事件等价,但会冒泡。浏览器支持:IE5.5+,Safari5.1+、Opera11.5+、Chrome、Firefox

 4)focusout:元素失去焦点时触发,与 blur 事件等价,但会冒泡。浏览器支持:IE5.5+,Safari5.1+、Opera11.5+、Chrome、Firefox

 5)DOMFocusIn:元素获得焦点时触发,与 focus 事件等价,但会冒泡。DOM3级事件中被废弃,浏览器支持:Opera

 6)DOMFocusOut:元素失去焦点时触发,与 blur 事件等价,但会冒泡。DOM3级事件中被废弃,浏览器支持:Opera

结合document.hasFocus() -->判断文档是否获取焦点,以及document.activeElement -->文档中获得焦点的元素,来确定用户的操作行为。

4.3 鼠标与滚轮事件

1)click:单击主鼠标按钮(鼠标左键)或按下回车键时触发

2)dblclick:双击主鼠标键(鼠标左键)时触发

3)mousedown:按下了任意鼠标按钮时触发

4)mouseup:释放鼠标按钮时触发

5)mouseenter:鼠标光标从元素外部首次移动到元素范围内时触发,这个事件不冒泡,而且光标移动到后代元素上不会触发。

6)mouseleave:在位于元素上方的鼠标光标移动到元素范围之外时触发,这个事件不冒泡,而且光标移动到后代元素上不会触发。

7)mousemove:当鼠标指针在元素内部移动是重复触发

8)mouseout:在鼠标指针位于一个元素上方,然后将其移动到另一个元素时触发。另一个元素可能位于前一个元素外部,也可能是这个元素的子元素。

9)mouseover:在鼠标指针位于一个元素外部,然后将其首次移动到另一个元素范围内时触发

10)mouseWheel: 滚轮事件,滚动页面时触发

 

页面所有的元素都支持鼠标事件,除了mouseenter 和 mouseleave,其他所有事件都会冒泡,也可以被取消。

在同一个元素上相机触发 mousedown 和mousedown 事件,才会触发 click 事件;只有触发两次 click 事件,才会触发 dblclick 事件。这个过程中有一个事件被取消,后面的事件就不会发生。

在 IE9+、Chrome、Firefox、Safari、Opera中,鼠标键按下、弹起发生的事件顺序:mousedown ----> mouseup ----> click ----> mousedown ----> mouseup ---->click ----> dblclick

在 IE8- 中,在双击中,会跳过第二个 mousedown 和 click,鼠标键按下、弹起发生的事件顺序:mousedown ----> mouseup ----> click ----> mouseup ----> dblclick

 

1) 鼠标事件发生时 ,事件对象保存了一些事件发生的位置信息

       客户区坐标:事件发生时鼠标指针在视口中的坐标,event.clientX,event.clientY

       页面坐标:事件发生时鼠标指针在页面中的坐标,event.pageX,event.pageY。IE8- 中事件对象不支持页面坐标,但可以通过客户区坐标和scrollLeft 和 scrollTop 计算出来。

       屏幕坐标:事件在整个屏幕中的坐标,event.screenX,event.screenY

    var clientCoordinates =  null;
    var pageCoordinates =  null;
    var screenCoordinates =  null;

    EventUtil.addHandler(btn,"click",function (event) {

        event = EventUtil.getEvent(event);

        clientCoordinates = {x:event.clientX,y:event.clientY};

        pageCoordinates = {x:event.pageX,y:event.pageY};
        if(pageCoordinates.x === undefined){
            pageCoordinates.x = event.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft);
        }
        if(pageCoordinates.y === undefined){
            pageCoordinates.y = event.clientY + (document.body.scrollTop || document.documentElement.scrollTop);
        }

        screenCoordinates = {x:event.screenX,y:event.screenY};

        console.log(clientCoordinates);
        console.log(pageCoordinates);
        console.log(screenCoordinates);

    });

2)修改键,shift、ctrl、alt、meta(Windows中的windows键,apple中的cmd键),这些键和鼠标事件可以配合完成一些事情。

鼠标事件中有四个布尔值属性,shiftKey、ctrlKey、altKey、metaKey,这些键按下,其值为true,反之为false。IE、Firefox不支持metaKey。

    EventUtil.addHandler(btn,"click",function (event) {

        event = EventUtil.getEvent(event);

        var keys = new Array();

        if(event.shiftKey){
            keys.push("shift");
        }
        if(event.ctrlKey){
            keys.push("ctrl");
        }
        if(event.altKey){
            keys.push("alt");
        }
        if(event.metaKey){
            keys.push("metaKey");
        }
        console.log("keys:" + keys.join(","));
    });

3)相关元素,event.relatedTarget,mouseover 和  mouseout 事件都会涉及把鼠标从一个元素的边界之内移动到另一个元素的边界之内。

对于 mouseover 事件:事件的主目标是获得光标的元素,相关元素是失去光标的元素;

对于 mouseout 事件:事件的主目标是失去光标的元素,相关元素是获得光标的元素。

 IE8- 不支持relatedTarget,但有相关信息:mouseover 事件,事件对象的 fromElement 属性; mouseou 事件,事件对象的 toElement 属性。IE9+都支持。

4)鼠标按钮,对于mousedown 和 mouseup 事件有 event.button,表示鼠标按下了哪个键:鼠标主键(左键),鼠标次键(右键),鼠标中间滚轮

DOM规定,0---->鼠标主键,1---->鼠标中间滚轮,2---->鼠标次键

 IE8- 事件对象也有 button 属性,但更详细,用三位二进制数表示,从低位到高位分别是:主键、次键、滚轮,按下键就是1,所以换成十进制就是:

0----> 没有按下键,1----> 按下主键,2----> 按下次键,3---->同时按下了主、次键,4---->按下滚轮,5---->同时按下了主键和滚轮,6---->同时按下了次键和滚轮,7---->同时按下了三个键。

mouseup事件中 button 属性表示的是释放哪个键。

对于click 事件,button 属性的值都是0。

 4)鼠标滚轮事件, mousewheel,DOMMouseScroll(Firefox) 

滚轮事件可以在任何元素上触发,最终会冒泡到 document(IE8-)或 window (IE9+、Opera、Chrome、Safari,Firefox)对象上。

mousewheel 事件包含鼠标事件的所有标准信息,另外还有一个 wheelDelta(detail,DOMMouseScroll事件)属性。

 鼠标向前滚动时 wheelDelta 是120,向后滚动 wheelDelta 是 -120

 在Firefox中,鼠标向前滚动时 detail 是 -3,向后滚动 detail 是 3

    function handleMOuseWheel(event) {

        event = EventUtil.getEvent(event);
        console.log(event.wheelDelta || -event.detail * 40);
    }

   EventUtil.addHandler(document,"mousewheel",handleMOuseWheel);
   EventUtil.addHandler(document,"DOMMouseScroll",handleMOuseWheel);

5)触摸设备

iOS 和 Android 设备没有鼠标,一般只能触发 click 事件

    a:不支持双击 dblclick 事件,双击浏览器窗口可能会放大画面

    b:轻击可单击元素触发 mousemove 事件,如果此操作会导致内容变化,将不再有其他事件发生;如果屏幕灭有一次变化,那么会依次发生mousedown、mouseup、click 事件。轻击不可单击的元素不会触发任何事件

          可单击元素是指 那些单击可产生默认操作的元素(如链接)或者指定了onclick 事件处理程序的元素。

    c:mousemove 事件也会触发mouseover 和 mouseout 事件

    d:两个手指放在屏幕上且页面随手指移动而滚动时会触发 mousewheel 和 scroll 事件

4.4 键盘与与文本事件

4.4.1 键盘事件

1)keydown 事件:在键盘上按下任意键时触发,如果按住不放的话,会重复触发

2)keypress 事件:在键盘上按下字符键时触发,如果按住不放的话,会重复触发

3)keyup 事件:释放按键时触发

只要获取到焦点,所有元素都可以发生 keydown、keypress、keyup 这三个事件,但通常是在文本输入时用到。如果按下了字符键,先是触发 keydown 事件,然后是 keypress 事件,最后是 keyup 事件。

键盘事件 也支持修改键,事件对象中有四个布尔值属性,shiftKey、ctrlKey、altKey、metaKey,这些键按下,其值为true,反之为false。IE、Firefox不支持metaKey。

4.4.2 键码 keyCode(键盘上按键的编码) 和 字符编码 charCode(ASCII编码),都是只读属性。

在 keydown 和 keyup 事件发生时,event对象会包含一个 keyCode 属性。对于字母字符和大键盘上的数字键, keyCode 的值与 ASCII 码中对应大写字母或数字的编码相同。同时event对象也有 charCode 属性,但值都为 0(IE8- 为 undefined)

在 keypress 事件发生时,event对象也会包含 keyCode 和 charCode 属性,且 keyCode 和 charCode 相同 ,都是对应字符的 ASCII 编码值(IE8- 和 早期Opera 中 charCode 为 undefined)。

 4.4.3 textInput 事件,DOM3 新添加的事件,在可编辑区域中输入字符时触发,类似 keypress 事件。事件对象有一个 data 属性,值是按下的键的字符。Chrome、Safari、Opera(高版本)、Edge支持,Firefox、IE不支持。

4.5 复合事件

是DOM3 新添加的一类事件,用于处理 IME(Input Method Editor,输入法编辑器)的输入序列。IME 可以让用户在输入物理键盘找不到的字符,比如中文输入。

1)compositionstart :在IME的文本复合系统打开时触发,表示要开始输入了

2)compositionupdate:在向输入字段中插入新字符时触发

3)compositionend:在IME 的文本年复合系统关闭时触发,表示返回正常键盘输入状态

这三个事件的事件对象中包含 data 属性,值是在各个阶段时的文本。

浏览器支持:Chrome、Edge

4.6 变动事件

DOM2级变动事件能在DOM中的某一部分发生变化时给出提示,变动事件是给XML 或 HTML DOM设计的

1)DOMSubtreeModified:在DOM结构中发生任何变化时触发,这个事件在其他变动事件触发后都会触发

2)DOMNodeInserted:在一个节点作为子节点被插入到另一个节点中触发

3)DOMNodeRemoved:在节点从其父节点中移除是触发

4)DOMNodeRemovedIntoDocument:在一个节点被直接插入文档或通过子树间接插入文档后触发,这个事件在DOMNodeInserted之后触发

5)DOMAttrModified:在特性被修改之后触发

6)DOMCharacterDataModified:在文本节点的值发生变化时触发

。。。。。。

4.7 HTML5 事件

为了能够满足更多实际需求, 浏览器制定了许多DOM规范之外的事件,HTML5事件就是HTML5规范中的除了DOM事件外的浏览器支持的事件。

1)contextmenu 事件,上下文菜单:在 windows 中右键单击,在Mac 中Ctrl+单击,触发事件。任何元素都可以响应这个事件,并且是冒泡的。contextmenu事件是鼠标事件,事件对象具有鼠标事件的位置属性,可以用来自定义上下文菜单。浏览器支持:IE、Firefox、Chrome、Safari、Opera11+;

2)beforeunload 事件:在页面窗口关闭(刷新)之前触发,显示弹框消息,让用户确定是否离开页面。浏览器支持:IE、Firefox、Chrome、Safari、Opera12+;

3)DOMContentLoaded 事件:在完整的DOM树形成后就会触发,不管图像、JavaScript文件、css 文件或其他资源是否已经加载完成。而load事件是页面中的所有资源都加载完后触发。DOMContentLoaded 事件支持在页面加载的早期添加事件处理程序。

     DOMContentLoaded 事件可以在 document 或 window 上注册,但事件的 target 属性时 document ,事件对象不会提供其他信息。始终会在 load 事件之前发生。浏览器支持:IE9+、Firefox、Chrome、Safari3.1+、Opera9+;

4)readystatechange 事件:当文档的 readystate 属性发生改变时触发,该事件对象不会提供任何信息。

     readystate 属性有下列可能的值:uninitialized(未初始化)--->对象存在但尚未初始化,loading(正在加载)--->对象正在加载数据,loaded(加载数据完毕)--->对象加载完成,interactive(可交互的)--->可以操作对象了,但还没有加载完全,complete(完成)--->对象加载完成

     readystate 的值并不是都会经历上述的所有阶段,对于document 可能就只有 interactive 和 complete 两个阶段。interactive 阶段大概与DOMContentLoaded 相同时刻触发。但interactive 和complete都无法确定是否比 load 事件先触发。interactive 也可能比complete更晚触发。

     浏览器支持:IE、Firefox4+、Chrome(高版本)、Safari(高版本)、Opera(高版本);

5)pageshow 和 pagehide 事件:分别在页面加载后和关闭前时触发。浏览器有一中 ”往返缓存“(back-forward cache,bfcache)机制,这个缓存中保存着整个页面。如果页面位于 bfcache 中,那么在此打开页面(通过“前进”或“后退”),就不会触发 load 事件。

     pageshow 事件:页面显示时触发。当第一次打开页面或重新加载时,pageshow 事件会在 load 事件之后发生;当页面在 bfcache 中,则在页面完全恢复时触发。

                                pageshow 事件的 event 对象包含一个 persisted 布尔值属性,如果页面被保存在 bfcache 中 persisted 的值为 true,反之,false。第一次触发 pageshow 时,persisted 一定是false。 通过检测 persist 属性的值来确定是否需要采取其他操作。

                                pageshow 事件处理程序必须注册在 window 上,虽然其事件的 target 是 document 。

     pagehide 事件:页面关闭刷新触发。在 unload 事件之前触发。处理程序必须注册在 window 上,其事件的 target 是 document。也包含 persisted 属性,如果页面关闭后被保存在 bfcache 中,那么 persisted 值为 true。

    浏览器支持:IE11、Firefox、Chrome、Safari、Opera。指定了 onunload 事件处理程序的页面会自动排除在 bfcache 之外,即使处理程序是空的。因为 onunload 最常用于撤销在 onload 中所执行的操作,而跳过 onload 后再次显示页面很可能会导致页面不正常。

6)hashchange 事件:在 URL 的参数列表(URL 中 # 号 后面的所有字符串)变化时触发。hashchange 事件的处理程序必须添加给 window 对象。event 对象 包含 两个属性:oldURL 和 newURL (只有Firefox,Chrome、Opera支持这两个属性);

     浏览器支持:IE8+、Firefox、Chrome、Safari、Opera

    document.addEventListener('DOMContentLoaded',function(){  //// 放在<head>中
        console.log('DOMContentLoaded');
    });
    document.addEventListener('readystatechange',function(){  // 放在<head>中
        if(document.readyState == "interactive" || document.readyState == "complete"){ // 检查其中一个就可以操作对象了

            console.log(document.readyState);
            document.removeEventListener("readystatechange",arguments.callee); // 执行一次
        }
    });
    document.onreadystatechange = function(){  // 放在<head>中
        if(document.readyState == "interactive" || document.readyState == "complete"){ // 检查其中一个就可以操作对象了

            console.log(document.readyState);
            document.onreadystatechange = null; // 执行一次
        }
    }


  EventUtil.addHandler(mydiv,"contextmenu",function(event){  // 也可以在 document 上注册 contextmenu 事件,用于处理整个页面的右击菜单事件
       event = EventUtil.getEvent(event);
       EventUtil.preventDefault(event);
       menu.style.left = event.clientX + "px";
       menu.style.top = event.clientY + "px";
       menu.style.visibility = "visible";
    });

    EventUtil.addHandler(document,"mouseup",function(){  // click
        menu.style.visibility = "hidden";
    });


    EventUtil.addHandler(window,"beforeunload",function(event){
        event = EventUtil.getEvent(event);
        EventUtil.preventDefault(event);
        var message = "确定关闭页面?";
        event.returnValue = message; //safari、 chrome
        return message; // IE、Firefox
    });


EventUtil.addHandler(window,"pagehide",function(event){

    pageHide.value = 'pagehide:'+event.persisted;

});


(function(){
    var showCount = 0;
    var loadCount = 0;

    EventUtil.addHandler(window,"load",function(){
        loadCount++;
        loadCountInput.value = loadCount;
        console.log("load")
    });
    EventUtil.addHandler(window,"pageshow",function(){
        showCount++;
        showCountInput.value = showCount+" "+event.persisted;
        console.log('pageshow:'+event.persisted);// 在pc机浏览器上,一般为false;在有的手机浏览器上为true,如果返回上一个页面试需要重新加载页面且event.persisted 为true,可手动reload()
    });

})();

  EventUtil.addHandler(window,"hashchange",function(event){
      console.log("oldURL:"+ event.oldURL + ", newURL:"+ event.newURL);
      console.log("current URL:"+ location.href);
  });

  EventUtil.addHandler(btn,"click",function(event){
      location.hash = "#hello";
  })

 

4.8 设备事件

 

   

posted @ 2019-03-28 13:47  zhanglw  阅读(239)  评论(0)    收藏  举报