Git Product home page Git Product logo

Comments (2)

shiiiiiiji avatar shiiiiiiji commented on May 18, 2024

事件类型

Web 浏览器中可能发生的事件有很多类型,不同类型的事件具有不同信息,DOM 3 级事件规定了以下几类事件:

  • UI(User Interface,用户界面) 事件
  • 焦点事件
  • 鼠标事件
  • 滚轮事件
  • 文本事件
  • 键盘事件
  • 合成事件
  • 变动(mutation)事件
  • ……

如何封装一个自定义事件???自定义事件有事件流的概念吗?另外,其实在当前混合式开发过程中,容器也会提供一些事件?事件 vs 生命周期?

UI 事件

现有 UI 事件如下:

  • DOMActivate 事件(已废弃):表示元素已经被用户操作(键盘/鼠标)激活
  • load 事件:
    • 当页面完全加载后在 window 上面触发
    • 当所有框架都加载完毕后在框架集上面触发
    • 当图像加载完毕后在 img 元素上面触发
    • 当嵌入的内容加载完毕后在 object 元素上面触发
  • unload 事件:
    • 当页面完全卸载后在 window 上面触发(只要用户从一个页面切换到另一个页面,就会发生 unload 事件)。利用这个事件最多的情况是清除引用,以避免内存泄露
    • 当所有框架都卸载完毕后在框架集上面触发
    • 当图像卸载完毕后在 img 元素上面触发
    • 当嵌入的内容卸载完毕后在 object 元素上面触发
  • abort 事件:在用户停止下载过程中,如果嵌入的内容没有加载完,则在 object 元素上面触发
  • error 事件:
    • 当发生 JavaScript 错误时在 window 上面触发
    • 当无法加载图像时在 img 元素上面触发
    • 当无法加载嵌入内容时在 object 元素上面触发
    • 当有一或多个框架无法加载时在框架集上面触发
  • select 事件:当用户选择文本框(input/textarea)中的一或多个字符时触发
  • resize 事件:当窗口或框架的大小变化时在 window 或框架上面触发
  • scroll 事件:当用户滚动带滚动条的元素中的内容时,在该元素上面触发。body 元素中包含所加载页面的滚动条

焦点事件

  • blur 事件:在元素失去焦点时触发,这个事件不会冒泡
  • DOMFocusIn 事件
  • DOMFocusOut 事件
  • focus 事件
  • focusin 事件
  • focusout 事件

当焦点从一个元素(A)移动到另一个元素(B),会依次触发下列事件:

  • focusout - A
  • focusin - B
  • blur - A
  • DOMFocusOut - A
  • focus - B
  • DOMFocusIn - B

鼠标和滚轮事件

  • click 事件
  • dbclick 事件
  • mousedown 事件
  • mouseenter 事件
  • mouseleave 事件
  • mousemove 事件
  • mouseout 事件
  • mouseover 事件
  • mouseup 事件

mousedown、mouseup、click、dbclick触发顺序:

  • mousedown 事件

  • mouseup 事件

  • click 事件

  • mousedown 事件

  • mouseup 事件

  • click 事件

  • dbclick 事件

  • 客户区坐标位置:clientX 和 clientY

  • 页面坐标位置:pageX 和 pageY

  • 屏幕坐标位置:screenX 和 screenY

  • 修改键:Shift、Ctrl、Alt、Meta(Windows/Cmd) => shiftKey、ctrlKey、altKey、metaKey

  • 相关元素:relatedTarget

  • 鼠标按钮:button

触摸设备

无障碍访问

键盘与文本事件

  • keydown 事件

  • keypress 事件

  • keyup 事件

  • 键码:keyCode

  • 字符编码:charCode

  • textInput事件

复合事件

变动事件

HTML 5 事件

  • contextmenu 事件
  • beforeunload 事件:之所以有发生在 window 对象上的 beforeunload 事件,是为了让开发人员有可能在页面卸载前阻止这一操作。这个事件会在浏览器卸载页面之前触发,可以通过它来取消卸载并继续使用原有页面。但是,不能彻底取消这个事件,因为那就相当于让用户无法离开当前页面了。为此,这个事件的意图是将控制权交给用户(弹出对话框)。
EventUtil.addHandler(window, "beforeunload", function(event){
    event = EventUtil.getEvent(event);
    var message = "I'm really going to miss you if you go.";
    event.returnValue = message;
    return message;
});
  • DOMContentLoaded 事件
    window 的 load 事件会在页面中的一切都加载完毕时触发,但这个过程可能会因为要加载的外部资源过多而破费周折。DOMContentLoaded 事件则在形成完整的 DOM 树之后就会触发,不理会图像、JavaScript 文件、CSS 文件或其他资源是否已经加载完毕。

要处理 DOMContentLoaded 事件,可以为 document 或 window 添加相应的事件处理程序(尽管这个事件会冒泡到 window ,但它的目标实际上是 document)

EventUtil.addHandler(document, "DOMContentLoaded", function(event){
    alert("Content loaded");
});

通常 DOMContentLoaded 事件既可以添加事件处理程序,也可以执行其他 DOM 操作。这个事件始终都会在 load 事件之前触发。

对于不支持 DOMContentLoaded 事件的浏览器,建议在页面加载期间设置一个时间为 0毫秒 的超时调用:

setTimeout(function(){
    // attach event handlers here
    // 在此添加事件处理程序
}, 0);

=> “在当前 JavaScript 处理完成后立即运行这个函数”,在页面下载和构建期间,只有一个 JavaScript 处理过程,因此超时调用会在该过程结束时立即触发。至于能否与 DOMContentLoaded 被触发的时间能否同步,主要还是取决于用户使用的浏览器和页面中的其他代码。为了确保有效,必须将其作为页面中的第一个超时调用,但也还是无法保证在所有环境中该超时调用一定会早于 load 事件被触发。

  • readystatechange 事件(注意兼容性与差异):readyState 属性

    • uninitialize(未初始化):对象存在但尚未初始化
    • loading(正在加载):对象正在加载数据
    • loaded(加载完毕):对象加载数据完成
    • interactive(交互):可以操作对象了,但还没有完全加载
    • compete(完成):对象已经加载完毕
  • pageshow 和 pagehide 事件

  • hashchange 事件
    HTML 5 新增了此事件,以便在 URL 的参数列表(及 URL 中“#”号后面的所有字符串)发生变化时通知开发人员。必须要把 hashchange 事件处理程序添加给 window 对象,然后 URL 参数列表只要变化就会调用。对应的事件对象额外包含两个属性:oldURL 和 newURL,分别保存着参数列表变化前后的完整 URL。

EventUtil.addHandler(window, "hashchange", function(event){
    alert("Current hash: " + location.hash);
});

var isSupported = ("onhashchange" in window); // 可能在 IE 下还有 bug

var isSupported = ("onhashchange" in window) && (document.documentMode === undefined || document.documentMode > 7);

设备事件

  • orientationchange 事件
  • MozOrientation 事件(Firefox)
  • deviceorientation 事件
  • devicemotion 事件

触摸与手势事件

Touch Events 规范 - W3C

  • 触摸事件
    • touchstart 事件:当手指触摸屏幕时触发,即使已经有一个手指放在了屏幕上也会触发
    • touchmove 事件:当手指在屏幕上滑动时连续地触发,在这个事件发生期间,调用 preventDefault() 可以组织滚动
    • touchend 事件: 当手指从屏幕上移开时触发
    • touchcancel 事件:当系统停止跟踪触摸时触发。(?关于此事件的确切触发时间,文档中没有明确说明)

上述事件都会冒泡,也都可以取消。虽然没在 DOM 规范中定义,但是是以兼容 DOM 的方式实现的 => 每个触摸事件都提供了在鼠标事件中常见属性:bubbles、cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、ctrlKey 和 metaKey。

除了常见的 DOM 属性外,触摸事件还包含下列三个用于跟踪触摸的属性:

  1. touches:表示当前跟踪的触摸操作的 Touch 对象的数组
  2. targetTouches:特定于事件目标的 Touch 对象的数组
  3. changeTouches:表示自上次触摸以来发生了什么改变的 Touch 对象的数组

每个 Touch 对象包含下列属性:clientX、clientY、identifier、pageX、pageY、screenX、screenY、target

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;
        }
    }
}
EventUtil.addHandler(document, "touchstart", handleTouchEvent);
EventUtil.addHandler(document, "touchend", handleTouchEvent);
EventUtil.addHandler(document, "touchmove", handleTouchEvent);
  • 手势事件
    • gesturestart
    • gesturechange
    • gestureend

from blog.

shiiiiiiji avatar shiiiiiiji commented on May 18, 2024

内存和性能

起因:由于事件处理程序可以为现代 Web 应用程序提供交互能力,所以开发者会向页面中添加大量的处理程序。(注意:真正引起内存问题的是注册在具体节点的事件处理程序,而不是事件和事件流)

内因:在 JavaScript 中,添加到页面上的事件处理程序数量会直接影响页面的整体运行性能。

  • 函数即对象,会占用内存。内存中对象越多,性能越差
  • 必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间

事件委托

对“事件处理程序过多”问题的解决方案就是——“事件委托”。事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

<ul id="myLinks">
    <li id="goSomewhere">Go somewhere</li>
    <li id="doSomething">Do something</li>
    <li id="sayHi">Say hi</li>
</ul>

传统做法:

var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
EventUtil.addHandler(item1, "click", function(event){
    location.href = "http://www.wrox.com";
});
EventUtil.addHandler(item2, "click", function(event){
    document.title = "I changed the document's title";
});
EventUtil.addHandler(item3, "click", function(event){
    alert("hi");
});

使用事件委托,在 DOM 树尽量最高的层次上添加一个事件处理程序:

var list = document.getElementById("myLinks");
EventUtil.addHandler(list, "click", function(event){
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);    // 事件目标是被单击的列表项
    switch(target.id){
        case "doSomething":
        document.title = "I changed the document's title";
        break;
    case "goSomewhere":
        location.href = "http://www.wrox.com";
        break;
    case "sayHi":
        alert("hi");
        break;
    }
});

移除事件处理程序

每当将事件处理程序指定给元素时,运行中的浏览器代码与支持页面交互的 JavaScript 代码之间就会建立一个连接。=>这种链接越多,页面执行起来就越慢(事件委托,可以限制建立的连接数量)。另外,在不需要的时候移除事件处理程序,也是解决这个问题的一种方案。=>内存中留有那些过时不用的“空事件处理程序”,也是造成 Web 应用程序内存与性能问题的主要原因。

造成空事件处理程序的原因有以下情况:

  • 从文档中移除带有事件处理程序的元素时。
    removeChild()、replaceChild()、innerHTML => 原来添加到元素中的事件处理程序极有可能无法被当作垃圾回收。
<div id="myDiv">
    <input type="button" value="Click Me" id="myBtn">
</div>
<script type="text/javascript">
var btn = document.getElementById("myBtn");
btn.onclick = function(){
    // ...
    document.getElementById("myDiv").innerHTML = "Processing..."; // 麻烦了!
    };
</script>

如果你知道某个元素即将被移除,最好手工移除事件处理程序:

<div id="myDiv">
    <input type="button" value="Click Me" id="myBtn">
</div>
<script type="text/javascript">
    var btn = document.getElementById("myBtn");
    btn.onclick = function(){
        // ...
        btn.onclick = null; // 移除事件处理程序
        document.getElementById("myDiv").innerHTML = "Processing...";
    };
</script>

注意:在事件处理程序中删除目标元素也能阻止事件冒泡,目标元素在文档中是事件冒泡的前提=>如果事先知道将来有可能使用 innerHTML 替换掉页面中的某一部分,那么就可以不直接将事件处理程序添加到该部分的元素中,而通过将事件处理程序指定给较高层次的元素,同样能够处理该区域中的事件。

  • 卸载页面的时候
    在页面卸载之前没有清理事件处理程序,会滞留在内存中。

最好的做法是在页面卸载之前,先通过 onunload 事件处理程序移除所有事件处理程序。(怎么移除???一个个移除很麻烦,事件委托移除很简单)

这个过程可以理解为,通过 onload 事件处理程序添加的东西,最后都要通过 onunload 事件处理程序将它们移除。

模拟事件

=== 模拟(触发)事件

事件,就是网页中某个特别值得关注的瞬间。

事件经常由用户操作或通过其他浏览器功能来触发,也可以使用 JavaScript 在任意时刻来触发特定的事件。

  • DOM 中的事件模拟:document.createEvent()
var btn = document.getElementById("myBtn");
// 创建事件对象
var event = document.createEvent("MouseEvents");
// 初始化事件对象
event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
// 触发事件
btn.dispatchEvent(event);

from blog.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.