事件类型总结

事件本质: 交互瞬间

事件表示:每个事件都由基于Event 接口的一个对象表示

UI事件

  • 定义:不一定与用户操作有关的。。呸。。

  • load事件:要想向DOM中添加一个新元素,就得确定页面加载完毕,因为防止在页面加载完毕前操作 document.body 导致错误。

    • window/document?

    • img:

      1
      2
      document.body.appendChild(image);
      image.src = "smile.gif"; // 新图像元素只要设置了 src 属性就开始下载,
  • unload:在文档被完全卸载后触发,一般利用于清除引用,避免内存泄漏

  • resize:The document view has been resized.(window对象上发生)

  • scroll:The document view or an element has been scrolled.(window对象上发生)

焦点事件

  • focus:元素获得焦点(不会冒泡

  • blur:元素失去焦点(不会冒泡

鼠标与滚轮事件

  • click:在元素上按下并释放任意鼠标按键、回车键

  • mousedown:在元素上按下任意鼠标按钮

  • mouseup:在元素上释放任意鼠标按键

1
单击事件:mousedown -> mouseup -> click
  • dbclick:在元素上双击鼠标按钮
    1
    双击事件:mousedown -> mouseup -> click -> mousedown -> mouseup -> click -> dbclick
  • mouseout: 指针移出元素,或者移到它的子元素上
  • mouseover:指针移到有事件监听的元素或者它的子元素内

    • 区别:out呢,是 target 元素是本身, relatedTarget 是别的元素。 over 正相反。
  • 鼠标坐标:

    • 视图窗口:event.clientx

    • 页面: event.pageX

    • 屏幕:event.screenX

  • 修改键:

    • event.shiftKey、ctrl、alt
  • 鼠标按钮:button 属性值。左右键:1/2/0

  • 鼠标滚轮:mousewheel

    • event.wheelDelta(+、-用来判断方向,数值不用关心)
  • 触摸设备:移动端以后再看。

键盘与文本事件

  • 虽然所有元素都支持,但一般用户通过文本框输入才使用。

  • keydown:按下任意按键

  • keypress:除 Shift, Fn, CapsLock 外任意键被按住. (连续触发)

  • keyup:释放任意按键
  • input:

    • 变动: input

    • 以下描述全部废弃

    • 跟keypress 区别是:一是只有可编辑区域才能出发。二是只有在用户按下能够输入实际字符的键才会被触发。

    • 因此主要考虑是字符,可以通过 evnet.data 获取用户输入的字符而非字符编码。换句话说,用户在没有按上档键情况下按 s 键,data 值就是 “s”,按下上档键后就是 “S”. 懵逼

  • 键码:envet.keycode 。它属性的值与 ASCII 码中对应小写字母或者数字的编码相同。而其他非字符键的键码有图。。

变动事件

!昨晚才看的变动事件,今天在 msn 上看时已经被废弃了,改用 MutationObserver 方案。过了5年变动就这么大了。

MSN

W3C

HTML5事件

  • contextmenu:右键菜单

  • beforeunload:window,document 及其资源即将被卸载。

  • DOMContentLoaded: 废弃
  • hashchange vs location : URL has changed
  • readystatechange(跳过)
  • pageshow/pagehide(跳过)

内存和性能

背景:在 js 中,添加到页面上的事件处理程序都将直接关系到页面的整体性能。导致这问题有两点原因:一是每个函数都是对象,都会占用内存,内存的对象越多,性能越差。二是必须提前指定所有事件处理程序而导致DOM 访问次数增加,会延迟整个页面的交互就绪时间。

事件委托

  • 做法简单来说:只指定一个事件处理程序,就可以管理某一类型的所有事件。比如说 click 事件会一直冒泡到 document 层次。
  • 例子如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    <body>
    <ul id="myLinks">
    <li id="goSomewhere">Go somewhere</li>
    <li id="doSomething">Do something</li>
    <li id="sayHi">Say hi</li>
    </ul>
    <script type="text/javascript">
    (function(){
    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;
    }
    });
    })();
    </script>
    </body>
    ```
    - 总结:只取得了一个DOM元素,只添加了一个事件处理程序。占用的内存更少,所有用到按钮的事件都适合采用事件委托事件。
    ### 移除事件处理程序
    - 每当事件处理程序指定给定的元素时,运行中的浏览器和支持页面交互的 js 代码就建立了一种连接。**这种连接越多,页面执行起来就越慢。**所以前面可以用事件委托限制建立连接的数量,另外,也应该注意在不需要的时候移除事件处理程序。 **内存中留有那些过时不用的 “空事件处理程序” ,也是造成 web 应用程序内存与性能问题的主要原因。**
    - 有两种情况造成“空事件处理程序”
    - removechild
    - xxx.innerHTML = "xxx";
    - 解决方法是手动移除事件处理程序:

    btn.onclick = function(){
    btn.onclick = null;
    xxx.innerHTML = “xxx”;

```

  • 另一种情况是卸载页面时,有些浏览器会没有清理干净事件处理程序,造成对象滞留在内存中。
    • 一般推荐的做法是在页面卸载之前,先通过 onload事件处理程序移除所有的事件处理程序。这样前面事件委托的优势就来啦,需要跟踪的 事件处理程序少了,移除就容易。