第十三章:事件类型(HTML5事件、设备事件、触摸与手势事件)

来源:互联网 发布:java localdate 编辑:程序博客网 时间:2024/05/19 11:45

事件

事件类型

HTML5事件

  • DOM规范没有涵盖所有浏览器支持的所有事件。很多浏览器还实现了一些自定义的事件。HTML5详尽列出了浏览器应该支持的所有事件。此处讨论得到浏览器完善支持的事件,其他事件会在其余地方讨论。

contextmenu事件

  • 可以简单地认为该事件是鼠标右键单击事件(在Windows中是右键单击,在Mac中是Ctrl+单击,以下默认为Windows)。该事件的名称叫上下文菜单,就像我们在桌面右键单击出来包含刷新的菜单一样。我们在页面上右键单击会出现默认菜单,如果要实现我们的自定义菜单,那我们除了将自己自定义的菜单显示以外,还得通过event.preventDefault()IE8-中用returnValue = false)取消默认的行为。
<!DOCTYPE html><html><head>    <title>ContextMenu Event Example</title></head><body>    <div id="myDiv">Right click or Ctrl+click me to get a custom context menu. Click anywhere else to get the default context menu.</div>    <ul id="myMenu" style="position:absolute;visibility:hidden;background-color:silver">        <li><a href="http://www.nczonline.net">Nicholas' site</a></li>        <li><a href="http://www.wrox.com">Wrox site</a></li>        <li><a href="http://www.yahoo.com">Yahoo!</a></li>    </ul>    <script type="text/javascript">        window.addEventListener("load", function(event){            var div = document.getElementById("myDiv");            div.addEventListener("contextmenu", function(event){                event.preventDefault();//取消默认行为                var menu = document.getElementById("myMenu");                menu.style.left = event.clientX + "px";                menu.style.top = event.clientY + "px";                menu.style.visibility = "visible";            });            document.addEventListener("click", function(event){                document.getElementById("myMenu").style.visibility = "hidden";            });        });    </script></body></html>
  • 支持contextmenu事件的浏览器有IE、Firefox、Safari、Chrome和Opera11+。

beforeunload事件

  • 该事件是为了让开发人员有可能在页面卸载前阻止这一操作。显示的消息会告知用户页面将被卸载,询问用户是否真的要关闭页面。
  • 不同浏览器设置消息有所不同。IE8-下需要为将该消息赋值给event.returnValue,其余浏览器多数是作为该事件处理程序函数的返回值。但是我测试下来,没办法改变Chrome的提示信息(查阅资料得知:Chrome从51 版(2016 年 4 月)起取消 onbeforeunload 对话框显示自订讯息功能,理由是防止自订讯息被用于诈骗用途。Edge、Firefox 及 Opera到目前都不支持自订讯息功能。毛法,不强求咯)。
<!DOCTYPE html><html><head>    <title>BeforeUnload Event Example</title></head><body>    <div id="myDiv">Try to navigate away from this page.</div>    <script type="text/javascript">        var addHandler = function(element, type, handler){            if (element.addEventListener){                element.addEventListener(type, handler, false);            } else if (element.attachEvent){                element.attachEvent("on" + type, handler);            } else {                element["on" + type] = handler;            }        };        var getEvent = function(event){            return event ? event : window.event;        }        addHandler(window, "beforeunload", function(event){            event = getEvent(event);            var message = "I'm really going to miss you if you go.";            event.returnValue = message;//IE通用            return message;//大多数浏览器包括IE9+            //今天我又做了一个测试,发现对于Chrome和Firefox而言,            //returnValue能够引导弹窗,而只return无效。        });    </script></body></html>

DOMContentLoaded事件

  • 该事件是对前面提到的load事件的改进,我们知道,load事件是在页面中的一切都加载完毕时触发(这里只谈页面,虽然元素也有load事件)。而DOMContentLoaded事件会在形成完整的DOM树之后就会触发,不理会图像、JavaScript文件、CSS文件或其他资源是否已经下载完毕。该事件意味着用户能够尽早地同页面交互
  • 该事件的目标是document,它会冒泡到window,所以我们可以为document或window添加相应的事件处理程序。
<!DOCTYPE html><html><head>    <title>DOMContentLoaded Event Example</title></head><body>    <div id="myDiv">DOMContentLoaded example - works only in Opera and Firefox</div>    <script type="text/javascript">        window.addEventListener("DOMContentLoaded", function(event){            alert("Content loaded.");//先执行        });        window.addEventListener("load", function(event){            alert("Window loaded.");        });    </script></body></html>
  • 对于不支持DOMContentLoaded事件的浏览器,我们可以用下面代码:
    setTimeout(function(){        //事件处理程序    },0)
  • 这段代码的意思是在当前JavaScript处理完成后立即运行这个函数。不过必须作为页面的第一个超时调用。即便如此,由于浏览器差异等等因素,也不能保证该超时调用一定会先于load事件触发(反正我测下来都是后于load事件触发的。)。

readystatechange 事件

  • IE为DOM文档中的某些部分提供了readystatechange事件(话虽这么说,Chrome后期也实现了这个事件)。这个事件的目的是提供与文档或元素的加载状态有关的信息。支持readystatechange事件的每个对象都有一个readyState属性(document也有这个属性),可能包含下列5个值中的一个。
    1. uninitialized(未初始化):对象存在但尚未初始化。
    2. loading(正在加载):对象正在加载数据。
    3. loaded(加载完毕):对象加载数据完毕。
    4. interactive(交互):可以操作对象了,但还没有完全加载。
    5. complete(完成):对象已经加载完毕。
  • 这些状态看起来很直观,但并非所有对象都会经历readyState 的这几个阶段。换句话说,如果某个阶段不适用某个对象,则该对象完全可能跳过该阶段;并没有规定哪个阶段适用于哪个对象。显然,这意味着readystatechange 事件经常会少于4 次,而readyState 属性的值也不总是连续的。
  • 对于document 而言,值为”interactive“的readyState 会在与DOMContentLoaded 大致相同的时刻触发readystatechange 事件。此时,DOM树已经加载完毕,可以安全地操作它了,因此就会进入交互(interactive)阶段。但与此同时,图像及其他外部文件不一定可用。
<!DOCTYPE html><html><head>    <title>DOMContentLoaded Event Example</title></head><body>    <div id="myDiv">DOMContentLoaded example - works only in Opera and Firefox</div>    <script type="text/javascript">        document.addEventListener("readystatechange", function(event){            if (document.readyState == "interactive"){                alert("Content loaded1");//IE和Chrome中先执行            }        });        document.addEventListener("DOMContentLoaded", function(event){            if (document.readyState == "interactive"){                alert("Content loaded2");            }        });        window.addEventListener("load", function(event){            alert("load loaded2");//最后        });    </script></body></html>
  • 另外, <script><link>元素也会触发readystatechange事件,可以用来确定外部的JavaScript 和CSS 文件是否已经加载完成。与在其他浏览器中一样,除非把动态创建的元素添加到页面中, 否则浏览器不会开始下载外部资源。基于元素触发的readystatechange 事件也存在同样的问题, 即readyState 属性无论等于”loaded” 还是”complete“都可以表示资源已经可用。有时候,readyState 会停在”loaded“阶段而永远不会“完成”;有时候,又会跳过”loaded“阶段而直接“完成”。于是,还需要像对待document 一样采取相同的编码方式。例如,下面展示了一段加载外部JavaScript 文件的代码。
  • 这个事件如此复杂,使用的时候要小心一点,我就不用了。

pageshow 和pagehide 事件

  • Firefox 和Opera 有一个特性,名叫“往返缓存”(back-forward cache,或bfcache),可以在用户使用浏览器的“后退”和“前进”按钮时加快页面的转换速度。这个缓存中不仅保存着页面数据,还保存了DOMJavaScript 的状态;实际上是将整个页面都保存在了内存里。如果页面位于bfcache 中,那么再次打开该页面时就不会触发load 事件(Chrome没有这个特性…)。
  • pageshow事件会在页面重新加载后,触发load事件之后触发。如果页面来自bfcache,则跳过load事件,直接触发pageshow事件。虽然pageshow的目标是document,但是我们必须得为window指定事件处理程序。
  • 除了通常的属性之外,pageshow 事件的event 对象还包含一个名为persisted 的布尔值属性。如果页面被保存在了bfcache 中,则这个属性的值为true;否则,这个属性的值为false(其实是指该页面是否是从bfcache中读取的)。
  • pageshow 事件对应的是pagehide 事件,该事件会在浏览器卸载页面的时候触发,而且是在unload 事件之前触发。与pageshow 事件一样,pagehidedocument 上面触发,但其事件处理程
    序必须要添加到window 对象。这个事件的event 对象也包含persisted 属性,不过其用途稍有不同。如果页面在卸载之后会被保存在bfcache 中,那么persisted 的值也会被设置为true
  • 由于我只有Chrome浏览器(IE就算了),以下是在Chrome中的测试代码(刷新页面,可以看到pagehide下的 event.persisted为false,也就是说不存入bfcache,所以也就没有接着测试了):
<!DOCTYPE html><html><head>    <title>PageShow/PageHide Event Example</title></head><body>    <script type="text/javascript">    (function(){        var showCount = 0;        window.addEventListener("load", function(){            alert("Load fired");                    });        window.addEventListener("pageshow", function(event){            showCount++;            alert("Show has been fired " + showCount + " times. Persisted? " + event.persisted);                    });        window.addEventListener("pagehide", function(event){            console.log("Hiding. Persisted? " + event.persisted);//如果alert会失效。就跟在beforeunload中alert一样被拒绝。        });    })();    </script></body></html>
  • 我还是想知道在Firefox里面的效果,忍了十三章还是下了Firefox。不过我找不到合适的例子。

hashchange 事件

  • HTML5 新增了hashchange 事件,以便在URL 的参数列表(及URL 中“#”号后面的所有字符串)发生变化时通知开发人员。之所以新增这个事件,是因为在Ajax 应用中,开发人员经常要利用URL 参数列表来保存状态或导航信息
  • 必须把hashchange事件处理程序添加给window对象。event对象中额外包含两个属性:oldURLnewURL
<!DOCTYPE html><html><head>    <title>Hash Change Example</title>    <script type="text/javascript" src="EventUtil.js"></script></head><body>    <p>Click each of these links to change the URL hash.</p>    <ul>        <li><a href="#up">Up</a></li>        <li><a href="#down">Down</a></li>    </ul>    <p>This example only works in browsers that <code>onhashchange</code>.</p>    <script type="text/javascript">        EventUtil.addHandler(window, "hashchange", function(event){            alert("Old URL: " + event.oldURL + "\nNew URL: " + event.newURL);        });    </script></body></html>
  • 支持hashchange 事件的浏览器有IE8+、Firefox 3.6+、Safari 5+、Chrome 和Opera 10.6+。在这些浏览器中,只有Firefox 6+、Chrome 和Opera 支持oldURL 和newURL 属性(此时就可以用到之前学过的location对象中的hash属性了)。

设备事件

  • 智能手机平板电脑的普及,为用户与浏览器交互引入了一种新的方式,而一类新事件也应运而生。

orientationchange事件

  • 苹果公司为移动Safari 中添加了orientationchange 事件,以便开发人员能够确定用户何时将设备由横向查看模式切换为纵向查看模式。移动Safari 的window.orientation 属性中可能包含3 个值:0 表示肖像模式,90 表示向左旋转的横向模式(“主屏幕”按钮在右侧),-90 表示向右旋转的横向模式(“主屏幕”按钮在左侧)。相关文档中还提到一个值,即180 表示iPhone 头朝下;但这种模式至今尚未得到支持。这里写图片描述
  • 所有iOS 设备都支持orientationchange 事件和window.orientation 属性。

MozOrientation事件

  • 这个事件和orientationchange事件差不多,是在window 对象上触发的,event 对象包含三个属性:x、y 和z。这几个属性的值都介于1 到-1 之间,表示不同坐标轴上的方向。在静止状态下,x 值为0,y 值为0,z 值为1(表示设备处于竖直状态)。**如果设备向右倾斜,x 值会减小;反之,向左倾斜,x 值会增大。类似地,如果设备向远离用户的方向倾斜,y 值会减
    小,向接近用户的方向倾斜,y 值会增大。z 轴检测垂直加速度度,1 表示静止不动,在设备移动时值会减小。(失重状态下值为0。)**

deviceorientation和devicemotion事件

  • 这两个事件都是关于手机在各个方向上的移动和角度加速度之类的,有兴趣的可以看书p395

触摸与手势事件

触摸事件

  • 有以下几个触摸事件:
    1. touchstart:当手指触摸屏幕时触发;即使已经有一个手指放在了屏幕上也会触发。
    2. touchmove:当手指在屏幕上滑动时连续地触发。在这个事件发生期间,调用preventDefault()可以阻止滚动。
    3. touchend:当手指从屏幕上移开时触发。
    4. touchcancel:当系统停止跟踪触摸时触发。关于此事件的确切触发时间,文档中没有明确说明。
  • 上述几个事件都会冒泡,都可以取消。每个触摸事件的event 对象都提供了在鼠标事件中常见的属性:bubbles、cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、ctrlKey 和metaKey
  • 除了常见的DOM属性外,触摸事件还包含下列三个用于跟踪触摸的属性:
    1. touches:表示当前跟踪的触摸操作的Touch 对象的数组。
    2. targetTouchs:特定于事件目标的Touch 对象的数组。
    3. changeTouches:表示自上次触摸以来发生了什么改变的Touch 对象的数组。
  • 每个Touch 对象包含下列属性:
    1. clientX:触摸目标在视口中的x 坐标。
    2. clientY:触摸目标在视口中的y 坐标。
    3. identifier:标识触摸的唯一ID。
    4. pageX:触摸目标在页面中的x 坐标。
    5. pageY:触摸目标在页面中的y 坐标。
    6. screenX:触摸目标在屏幕中的x 坐标。
    7. screenY:触摸目标在屏幕中的y 坐标。
    8. target:触摸的DOM 节点目标。
  • 由于我电脑没有发wifi的功能,我手机也连不上我的电脑,所以这些都没法测试了。以下是测试代码:
<!DOCTYPE html><html><head>    <title>Touch Events Example</title>    <meta name="viewport" content="width=device-width, user-scalable=no"></head><body>    <p>Touch anywhere on the screen. This only works on an iPhone or iPod Touch running iPhone 2.x software.</p>    <div id="output">     </div>    <script type="text/javascript">        function handleTouchEvent(event){            //only for one touch            if (event.touches.length == 1){                var output = document.getElementById("output");                switch(event.type){                    case "touchstart":                        output.innerHTML = "Touch started (" + event.touches[0].clientX + "," + event.touches[0].clientY + ")";                        break;                    case "touchend":                        output.innerHTML += "<br>Touch ended (" + event.changedTouches[0].clientX + "," + event.changedTouches[0].clientY + ")";                        break;                    case "touchmove":                        event.preventDefault();  //prevent scrolling                        output.innerHTML += "<br>Touch moved (" + event.changedTouches[0].clientX + "," + event.changedTouches[0].clientY + ")";                        break;                }            }        }        document.addEventListener("touchstart", handleTouchEvent, false);        document.addEventListener("touchend", handleTouchEvent, false);        document.addEventListener("touchmove", handleTouchEvent, false);    </script></body></html>

手势事件

  • 有三个手势事件,分别介绍如下:
    1. gesturestart:当一个手指已经按在屏幕上而另一个手指又触摸屏幕时触发。
    2. gesturechange:当触摸屏幕的任何一个手指的位置发生变化时触发。
    3. gestureend:当任何一个手指从屏幕上面移开时触发。
  • 触摸事件和手势事件之间存在某种关系。当一个手指放在屏幕上时,会触发touchstart 事件。如果另一个手指又放在了屏幕上,则会先触发gesturestart 事件,随后触发基于该手指的touchstart事件。如果一个或两个手指在屏幕上滑动,将会触发gesturechange 事件。但只要有一个手指移开,就会触发gestureend 事件,紧接着又会触发基于该手指的touchend 事件。
  • 与触摸事件一样,每个手势事件的event 对象都包含着标准的鼠标事件属性:bubbles、cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、ctrlKey 和metaKey。此外,还包含两个额外的属性:rotation 和scale。其中,rotation 属性表示手指变化引起的旋转角度,负值表示逆时针旋转,正值表示顺时针旋转(该值从0 开始)。而scale属性表示两个手指间距离的变化情况(例如向内收缩会缩短距离);这个值从1 开始,并随距离拉大而增长,随距离缩短而减小。

小结

  • 这篇文章内容多数枯燥(用的少),所以copy居多。
原创粉丝点击