• JavaScript基础笔记(九)事件


    事件

    一、事件流

    事件流描述的是从页面中接收事件的顺序。

    一)事件冒泡

    IE的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点。

    如:div------>body------->html

    二)事件捕获

    Netscape的事件流叫做事件捕获,与事件冒泡的顺序相反。

    虽然事件捕获是 Netscape Communicator 唯一支持的事件流模型,但 IE9SafariChromeOpera
    Firefox 目前也都支持这种事件流模型。尽管“DOM2 级事件”规范要求事件应该从 document 对象
    开始传播,但这些浏览器都是从 window 对象开始捕获事件的。
    由于老版本的浏览器不支持,因此很少有人使用事件捕获。我们也建议读者放心地使用事件冒泡,
    在有特殊需要时再使用事件捕获。

    三)DOM事件流

    DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。

    即使“DOM2 级事件”规范明确要求捕
    获阶段不会涉及事件目标,但 IE9SafariChromeFirefox Opera 9.5 及更高版本都会在捕获阶段触
    发事件对象上的事件。结果,就是有两个机会在目标对象上面操作事件。

    二、事件处理程序

    而响应某个事件的函数就叫做事件处理程序 ,事件处理程序名字多以"on"开头。

    一)HTML事件处理程序

    不用它

    二)DOM0级事件处理程序

    通过 JavaScript 指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。

    每个元素(包括 window document)都有自己的事件处理程序属性,
    将这种属性的值设置为一个函数,就可以指定事件处理程序

    <head>
        <meta charset="UTF-8">
        <title>Test</title>
        <script>
            window.onload = function (ev) {
                var btn = document.getElementById("bt1");
                btn.onclick = function () {
                    alert(this.id);  //this指向当前元素
                }
    
                //删除事件处理程序
                btn.onclick = null;
            }
        </script>
    </head>
    <body>
    <form action="post">
        <input type="button" id="bt1" value="button">
    </form>
    </body>

    以这种方式添加的事件处理程序,会在事件的冒泡阶段被处理。

    三)DOM2级事件处理程序

    DOM2级事件定义了两个方法:

    1.addEventListener(eventName,func,boolean)

    eventName:事件名

    func:事件处理程序

    boolean:当为true时候表示在捕获阶段调用事件处理程序。使用DOM2级方法的好处是可以添加多个事件处理程序,被添加的程序会一次执行。

    window.onload = function (ev) {
                var btn = document.getElementById("bt1");
                btn.addEventListener("click", function () {
                    alert(this.id);
                },true);
                
                btn.addEventListener("click", function () {
                    alert("Ha li lu ya!");
                },true);
            }

    2.removeEventListener(eventName,func,boolean)

    注意:该函数"不删无名之辈"

    其他略

    三、事件对象

    在触发 DOM 上的某个事件时,会产生一个事件对象 event,这个对象中包含着所有与事件有关的
    信息。包括导致事件的元素、事件的类型以及其他与特定事件相关的信息。例如,鼠标操作导致的事件
    对象中,会包含鼠标位置的信息,而键盘操作导致的事件对象中,会包含与按下的键有关的信息。所有
    浏览器都支持 event 对象,但支持方式不同。

    一)DOM中的事件对象

    在事件处理程序内部,对象 this 始终等于 currentTarget 的值,而 target 则只包含事件的实
    际目标。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Test</title>
        <script>
            window.onload = function () {
                //点击bt1时得到
                document.body.onclick = function (event) {
                    alert(event.currentTarget === document.body); //true
                    alert(this === document.body);  //true
                    alert(event.target === document.getElementById("bt1"));  //true 点击bt2时为false
                }
            }
        </script>
    </head>
    <body>
    <form action="post">
        <input type="button" id="bt1" value="button">
        <input type="button" id="bt2" value="button2">
    </form>
    </body>
    </html>

    只有 cancelable 属性设置为 true 的事件,才可以使用 preventDefault()来取消其默认行为。
    另外, stopPropagation()方法用于立即停止事件在 DOM 层次中的传播,即取消进一步的事件
    捕获或冒泡。

    window.onload = function () {
                var bt = document.getElementById("bt1");
                bt.onclick = function (ev) {
                    alert("Clicked button!");
                    ev.stopPropagation(); //阻止事件进一步传播到body元素
                }
    
                document.body.onclick = function (ev) {
                    alert("Clicked body !");
                }
            }

    事件对象的 eventPhase 属性,可以用来确定事件当前正位于事件流的哪个阶段。如果是在捕获阶
    段调用的事件处理程序,那么 eventPhase 等于 1;如果事件处理程序处于目标对象上,则 eventPhase 等于 2;如果是在冒泡阶段调用的事件处理程序, eventPhase 等于 3 .

    只有在事件处理程序执行期间, event 对象才会存在;一旦事件处理程序执行完
    成, event 对象就会被销毁

    四、事件类型

    DOM3级有以下几类事件

    一)UI事件

    UI事件是指那些不一定与用户操作有关的事件。

    1)DOMActivate:表示元素被激活,不建议使用。

    2)load事件:

    当页面完全加载(包括所有图像、js文件、CSS外部文件)后,事件会在window上触发,所有框架加载完成后在框架元素上触发,

    当图像加载完毕后在图像上触发,当嵌入的内容加载完毕后在<object>元素上触发。

    3)unload事件:

    unload事件在页面被完全卸载后触发,当用户从一个页面切换到另一个页面,就会触发该事件。

    而利用这个情况最多的是清除引用,以避免内存泄漏。

    3)resize事件:

    当浏览器窗口调整到一个新的宽度或者高度时,就会触发resize事件。该事件在window上触发。

    二)焦点事件

    在页面元素获得或失去焦点时触发。

    1)blur:元素失去焦点时触发,该事件不会冒泡,所有浏览器支持。

    2)focus: 在元素获得焦点时触发,该事件不会冒泡,所有浏览器支持。

    3)focusin:同上,但会冒泡。

    4)focusout:元素失去焦点时触发,会冒泡。

    三)鼠标与滚轮事件

    DOM3级事件:

    1)click:在用户单击主鼠标键或者按下回车键时触发。

    2)dbclick:双击鼠标时触发。

    3)mousedown:按下任意鼠标键时触发,不能通过键盘触发该事件。

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

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

    6)mousemove:当鼠标指针在元素内部移动时重复地触发。不能通过键盘触发这个事件。

    7)mouseout:在鼠标指针位于一个元素上方,然后用户将其移入另一个元素时触发。又移入的另
    一个元素可能位于前一个元素的外部,也可能是这个元素的子元素。不能通过键盘触发这个事件。

    8)mouseover:在鼠标指针位于一个元素外部,然后用户将其首次移入另一个元素边界之内时触
    发。不能通过键盘触发这个事件。

    9)mouseup:在用户释放鼠标按钮时触发。不能通过键盘触发这个事件。

    页面上的所有元素都支持鼠标事件。除了 mouseenter mouseleave,所有鼠标事件都会冒泡,
    也可以被取消,而取消鼠标事件将会影响浏览器的默认行为。取消鼠标事件的默认行为还会影响其他事
    件,因为鼠标事件与其他事件是密不可分的关系。
    只有在同一个元素上相继触发 mousedown mouseup 事件,才会触发 click 事件;如果
    mousedown mouseup 中的一个被取消,就不会触发 click 事件。类似地,只有触发两次 click
    件,才会触发一次 dblclick 事件。如果有代码阻止了连续两次触发 click 事件(可能是直接取消 click
    事件,也可能通过取消 mousedown mouseup 间接实现),那么就不会触发 dblclick 事件了。这 4
    个事件触发的顺序始终如下:
    (1) mousedown
    (2) mouseup
    (3) click
    (4) mousedown
    (5) mouseup
    (6) click
    (7) dblclick
    显然, click dblclick 事件都会依赖于其他先行事件的触发;而 mousedown mouseup
    不受其他事件的影响。

    1.客户区坐标位置

    鼠标事件都是在浏览器视口中的特定位置上发生的。这个位置信息保存在事件对象的 clientX
    clientY 属性中。

    2.页面坐标位置

    通过客户区坐标能够知道鼠标是在视口中什么位置发生的,而页面坐标通过事件对象的 pageX
    pageY 属性,能告诉你事件是在页面中的什么位置发生的。换句话说,这两个属性表示鼠标光标在页面中的位置,

    因此坐标是从页面本身而非视口的左边和顶边计算的。在页面没有滚动的情况下 pageX pageY 的值与 clientX clientY 的值相等。 

    3.屏幕坐标位置

    screenX screenY 属性 

    4.修改键

    虽然鼠标事件主要是使用鼠标来触发的,但在按下鼠标时键盘上的某些键的状态也可以影响到所要
    采取的操作。这些修改键就是 ShiftCtrlAlt Meta(在 Windows 键盘中是 Windows 键,在苹果机中
    Cmd 键),它们经常被用来修改鼠标事件的行为。 DOM 为此规定了 4 个属性,表示这些修改键的状
    态: shiftKeyctrlKeyaltKey metaKey。这些属性中包含的都是布尔值,如果相应的键被按
    下了,则值为 true,否则值为 false

    5.相关元素

    在发生 mouseover mouserout 事件时,还会涉及更多的元素。这两个事件都会涉及把鼠标指
    针从一个元素的边界之内移动到另一个元素的边界之内。对 mouseover 事件而言,事件的主目标是获
    得光标的元素,而相关元素就是那个失去光标的元素。类似地,对 mouseout 事件而言,事件的主目标
    是失去光标的元素,而相关元素则是获得光标的元素。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Test</title>
        <script>
            window.onload = function () {
                var d = document.getElementById("myDiv");
                d.onmouseout = function (ev) {
                    var t = ev.target;
                    var rt = ev.relatedTarget;
                    alert("Mouse out of " + t.tagName + " to " + rt.tagName);
                }
            }
        </script>
    </head>
    <body>
        <div id="myDiv" style="background-color: aquamarine; height: 100px;  100px;"></div>
    </body>
    </html>

    这个例子会在页面上显示一个<div>元素。如果鼠标指针一开始位于这个<div>元素上,然后移出
    了这个元素,那么就会在<div>元素上触发 mouseout 事件,相关元素就是<body>元素。与此同时,
    <body>元素上面会触发 mouseover 事件,而相关元素变成了<div>
    DOM 通过 event 对象的 relatedTarget 属性提供了相关元素的信息

    五、内存和性能

     JavaScript 中,添加到页面上
    的事件处理程序数量将直接关系到页面的整体运行性能。导致这一问题的原因是多方面的。首先,每个
    函数都是对象,都会占用内存;内存中的对象越多,性能就越差。其次,必须事先指定所有事件处理程
    序而导致的 DOM 访问次数,会延迟整个页面的交互就绪时间。

    提升性能方法:

    一)事件委托

    对“事件处理程序过多”问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个事
    件处理程序,就可以管理某一类型的所有事件。例如, click 事件会一直冒泡到 document 层次。也就
    是说,我们可以为整个页面指定一个 onclick 事件处理程序,而不必给每个可单击的元素分别添加事
    件处理程序。

    二)移除事件处理程序

    在不需要的时候移除事件处理程序也是一种解决方法。

    btn.onclick = null //移除事件处理程序

    如果在页面被卸载之前没有清理干净事件处理程序,那它们就会滞留在内存中。每次加载完页面再卸载页面时(可能是在两个页
    面间来回切换,也可以是单击了“刷新”按钮),内存中滞留的对象数目就会增加,因为事件处理程序
    占用的内存并没有被释放。 最好的做法是在页面卸载之前,先通过 onunload 事件处理程序移除所有事件处理程序。 

    Simple is important!
  • 相关阅读:
    Java集合框架
    数字翻转
    Servlet的一些细节
    tomcat9配置https
    JavaWeb_打包web应用war
    JavaWeb_tomcat设置默认应用
    JavaWeb_增强for循环
    JavaWeb_静态导入、自动拆箱/装箱
    JavaWeb_泛型(Generic)
    54字符流中第一个不重复的字符
  • 原文地址:https://www.cnblogs.com/Shadowplay/p/8474126.html
Copyright © 2020-2023  润新知