js红宝石 第十七章-事件

JavaScript和HTML的交互是通过事件实现的

可以用仅仅在事件发生时执行的监听器订阅事件

17.1 事件流

事件流描述了页面接收事件的顺序

17.1.1 事件冒泡

IE事件流被称为事件冒泡

当事件触发后,会从被点击的元素一直沿着DOM树往上爬,直到document对象为止

17.1.2 事件捕获

还有一种事件流叫事件

当事件触发后,会从document对象一直沿着DOM树往下,直到被点击的元素为止

17.1.3 DOM事件流

事件流分为3个阶段:

事件捕获  到达目标  事件冒泡

先向下到达事件,再回到document

17.2 事件处理程序

为响应事件而调用的函数被称为事件处理程序(监听器)

监听器的名字以"on"开头 onclick,onload...

17.2.1 HTML事件处理程序

特定元素的每个事件都可以使用事件处理程序的名字,以HTML的形式来指定

  <body>
    <button onclick="showMsg()">click me</button>
    <script>
      function showMsg(){
        console.log("I was clicked");
      }
    </script>
  </body>

这种方式会创建一个函数封装属性的值,产生一个特殊的局部变量event

document和元素自身的成员都可以当成局部变量访问到

17.2.2 DOM0事件处理程序

每个元素都有事件程序属性,给这个值赋函数即可

  <body>
    <button class="myBth">click me</button>
    <script>
      let btn = document.querySelector('.myBth')
      btn.onclick = function(e){
        console.log(e);
      }
    </script>

17.2.3 DOM2事件处理程序

定义了两个方法:addEventListener() 和 removeEventListener()

接收三个参数:

事件名

事件处理函数

布尔值: true代表在捕获阶段指向,false代表在冒泡阶段调用

  <body>
    <button class="myBtn">click me</button>
    <script>
      let btn = document.querySelector('.myBtn')
      btn.addEventListener(
        'click',
        (e) => {
          console.log(e)
        },
        true
      )
    </script>
  </body>

removeEventListener()则需要使用和addEventListener()一样的参数来移除

这意味着向上面一样使用匿名函数创建的addEventListener()无法被移除

但是像下面的例子就有效

  <body>
    <button class="myBth">click me</button>
    <script>
      let btn = document.querySelector('.myBth')

      let handler = function (e) {
        console.log(e)
      }

      btn.addEventListener('click', handler, true)

      btn.removeEventListener('click', handler, true)
    </script>
  </body>

一般情况下,推荐在冒泡阶段进行程序捕获,因为兼容性好

17.2.4 IE事件处理程序

attachEvent() 和 detachEvent() 现在好像用不了了

17.2.5 跨浏览器事件处理程序

可以封装一个如下类:支持DOM0,DOM2和IE浏览器的事件处理程序

        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
          }
        },
        removeHandler: function (element, type, handler) {
          if (element.removeEventListener) {
            element.removeEventListener(type, handler, false)
          } else if (element.detachEvent()) {
            element.detachEvent('on' + type, handler)
          } else {
            element['on' + type] = null
          }
        }
      }

17.3 事件对象

再DOM中发生事件时,所有相关信息都会被收集并且放在一个evevt对象中

17.3.1 DOM事件对象

event对象是传给事件处理程序的唯一参数.不管以哪种方式指定,都会传入

  <body>
    <button class="myBtn">click me</button>
    <script>
        let btn = document.querySelector('.myBtn')
        btn.onclick = function(e){
          console.log(e.type);
        }

        btn.addEventListener('click',(e)=>{console.log(e.type);},false)
    </script>
  </body>

event的实行和方法:p499

在处理程序内部

this对象 = currentTarget

target只包含事件的实际目标

preventDefault()阻止事件默认动作,如<a>的跳转

stopPropagation()阻止时间在DOM流中传播

eventPhase可以用来确定事件流所处阶段

17.3.2 IE事件对象

IE事件对象只是window对象的一个属性

17.4 事件类型

DOM3定义了如下事件类型:

用户界面事件 UIEvent

焦点事件 FocusEvent

鼠标事件 MouseEvent

滚轮事件 WhellEvent

输入事件 InputEvent

键盘事件 KeyboardEvent

合成事件 CompositionEvent

17.4.1 用户界面事件

load 加载完成时触发

unload 完全卸载后触发

abort <object>被用户终止下载时触发

select 在文本框上选择了一个或多个字符时触发

resize 窗口被缩放时触发

scroll 滚动滚动条时触发

大多数HTML事件和window对象和表单控件有关

17.4.2 焦点事件

blur 失去焦点触发 不冒泡

focus 获得焦点触发 不冒泡

focusin 获得焦点时触发 focus的冒泡版

focusout 失去焦点时触发blur的冒泡版

17.4.3 鼠标和滚轮事件

click 左键单击或键盘回车

dbclick 左键双击

mousedown 任意鼠标键

mouseenter 光标从元素外移到元素内 不冒泡

mouseleave 光标从元素内移到元素外 不冒泡

mousemove 光标在元素上移动时反复触发

mouseout 光标从一个到另一个元素时触发

mouseover 光标从元素外部到元素内部时触发

mouseup 释放鼠标按键时触发

客户端坐标

事件对象event中的clientX和clientY表示事件发生时鼠标在视口中的坐标

事件对象event中的pageX和pageY表示事件发生时鼠标在页面中的坐标

事件对象event中的screenX和screenY表示事件发生时鼠标在屏幕中的坐标

修饰键

event对象中的下面四个属性:

shiftKey

ctrlKey

altKey

metaKey

分别对应键盘的四个按键

相关元素

mouseover和mouseout存在事件相关的其他元素

mouseover主要目标是获得光标的元素,相关目标是失去光标的元素

mouseout则相反

鼠标按键

event对象会有一个button属性,

0表示左键 1表示中键 2表示右键

额外事件信息

event上定义了detail属性,表示在给定位置上的单击次数

如果鼠标在mousedown和mouseup之间移动了,则会清零

mousewheel事件

mousewheel的event对象中有一个wheelData的新属性,通过其正负可以知道滚轮的滚动方向

触摸屏设备

不支持dbclick

单指点可以触发mousemove事件

mousemove也会触发mouseover和mouseout

双指点屏幕并滑动会触发mousewheel和scroll

17.4.4 键盘与输入事件

keydown 按下键盘触发,并且一直按住会一直触发

keypress 废弃

keyup 抬起键盘时触发

textInput是对keypress的扩展,textInput会在文本被插入到文本框之前触发

1.键码

在keyup和keydown事件中

在event的keyCode中会保存一个键码,和小写的ASCLL码一致

2.字符编码

event上设置了charCode属性,只要发生了keypress事件这个属性才会被设置值,包含的时按键字符对应的ASCLL编码

一旦有了字符编码,就可以用String.fromCharCode()把其转化为实际的字符

3.DOM3的变化

DOM3未定义charCode,而是定义了key和char

key的值为文本字符/键名

char属性在按下非字符时为null

4.textInput

textInput只在可编辑节点上触发,而且只有新增字符时才触发(删除时不触发)

textInput的event事件上有data属性,始终包含输入的字符(不是编码)

还有inputMethod方法,表示输入的手段 p521

17.4.5 合成事件

合成事件时DOM3新增的,用于处理IME输入时的复杂输入序列

合成事件有以下三种:

compositionstart IME文本系统打开时触发,表示输入即将开始

compositionupdate 在新字符插入输入字段时触发

compositionend IME文本合成系统关闭时触发,表示恢复正常键盘

事件目标是接收文本的输入字段,唯一增加的属性是data

17.4.6 变化事件

变化事件已经被Mutation Observers取代

17.4.7 HTML5事件

DOM规范并未涵盖所有浏览器支持的事件,下面列出了H5得到了浏览器较好支持的一些事件

1.contextmenu事件

自定义菜单

      window.addEventListener('load', (e) => {
        let div = document.querySelector('#myDiv')

        div.addEventListener('contextmenu', (e) => {
          e.preventDefault() //防止默认菜单弹出

          let menu = document.getElementById('myMenu')
          menu.style.left = e.clientX + 'px'
          menu.style.top = e.clientY + 'px'
          menu.style.visibility = 'visible'
        })

        document.addEventListener('click', (e) => {
          document.getElementById('myMenu').style.visibility = 'hidden'
        })
      })

2.beforeunload

给开发者提供阻止页面被卸载的机会

事件会向用户显示一个确认框

3.DOMContentLoaded事件

DOMContentLoaded事件会在DOM树构建完成后立即触发,因此DOMContentLoaded事件可以让开发者在外部资源下载的同时就能指定事件处理程序,从而让用户能更快的与页面交互

4.readystatechange事件

提供文档或元素加载状态的信息

每个对象都有一个readyState属性:

uninitialized: 对象没有初始化

loading: 对象正在加载数据

loaded: 对象已经加载完数据

interactive: 对象可以交互,但是没有加载完成

complete: 对象加载完成

5.pageshow和pagehide事件

处理程序添加给window

往返缓存,在前进和后退时加快速度,实际上是吧整个页面都存在内存里

如果页面来自内存,就不会触发load事件

pageshow会在页面显示时触发,无论是否来自缓存

事件对象中persisted属性可以检测页面有无缓存

pageshow会在页面被卸载时触发

事件对象中persisted属性表示页面在卸载之后会不会被保存在往返缓存中

6.hashchange事件

当URL散列值发生变化时通知

17.4.8 设备事件

设备事件可以确定用户使用设备的方式

1.orientationchange事件

表示用户当前处于竖放还是平放

2.deviceorientation事件

获取用户加速计信息

3.devicemotion事件

用于提示设备实际上在移动

17.4.9 触摸以及手势事件

1.触摸事件

touchstart: 手指放到了屏幕上

touchmove: 手指在屏幕上滑动时连续触发  可以用preventDefault()阻止滚动

touchend: 手指从屏幕移开时触发

touchcancel: 系统停止跟踪触摸时触发

2.手势事件

gesturestart: 一个手指已经放到屏幕上,再把另一个手指放上去时触发

gesturechange: 任何一个手指在屏幕上的位置变化时触发

gestureend: 任何一个手指离开屏幕时触发

17.4.10 事件参考

p535

17.5 事件性能

在JavaScript中,页面中事件处理程序的数量与页面整体性能直接相关

可以使用下面的方法改善页面性能:

17.5.1 事件委托

事件委托利用冒泡,可以只使用一个事件处理程序来管理一种类型的事件

这意味着可以为整一个页面指定一个onclick,而不用为每个元素都指定一个

      let list = document.getElementById('myLinks')
      list.addEventListener('click', (e) => {
        let target = e.target

        switch (target.id) {
          case 'doSomething':
            document.title = 'title changed'
            break
          case 'goSomewhere':
            location.href = 'url'
            break
          case 'sayhi':
            console.log('hi')
            break
        }
      })

17.5.2 删除事件处理程序

及时删除事件处理程序可以有效提高性能

无用事件长驻内存会导致性能不佳

原因有两个:

1.删除了带有事件处理程序的节点

在删除之前注销程序

      let btn = document.getElementById("myBtn")
      btn.onclick = function(){
        //删除事件
        btn.onclick = null
        document.getElementById("myBtn").innerText = "Processing ... "
      }

2.页面残留

页面卸载之后如果事件处理程序没有被清理,则还会残留在内存中

最好在onunload事件中删除所有事件

17.6 模拟事件

通过JavaScript可以任何时候触发任意事件

p543

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值