每天一点,学习JavaScript【事件】

1.EventTarget接口

1.1 概 述

DOM的事件操作(监听和触发),都定义在EventTarget接口。所有节点对象都部署了这个接口,其他一些需要事件通信的浏览器内置对象(比如,XMLHttpRequest AudioNode AudioContext )也部署了这个接口。
该接口主要提供三个实例方法

  • addEventListener: 绑定事件的监听函数
  • removeEventListener: 移除事件的监听函数
  • dispatchEvent: 触发事件

1.2 EventTarget.addEventListener()

target.addEventListener(type,listener[,useCapture])

listener[,useCapture] 表示listener,useCapyure或者listener。[]符号表示非必须
该方法接收三个参数

  • type: 事件名称,大小写敏感
  • listener: 监听函数。事件发生时,会调用该监听函数
  • useCapture

    • 1.capture:布尔值,表示监听函数是否在捕获阶段capture)触发,默认为false
    • 2.once:布尔值,表示监听函数是否只触发一次,然后就自动移除 默认{once:false}
    • 3.passive:布尔值,表示监听函数不会调用事件的(preventDefault)方法,如果今天函数调用了,浏览器会输出警告⚠️,但不是错误

1.3 EventTarget.removeEventListener()

手动移除addEventListener方法添加的事件监听函数。该方法没有返回值,且附加的三个参数必须和要被移除的addEventListener参数一模一样.即removeEventListener方法移除的监听函数,必须是addEventListener方法添加的那个监听函数,而且必须在同一元素节点,否砸无效

1.4 EventTarget.dispatchEvent()

代替人工的手动触发,使用脚本进行触发事件。该方法返回一个布尔值,只要有一个监听函数调用了Event.preventDefault()(阻止默认事件),则返回false,否则为true

事件模型

  • 监听函数

    • HTMLon-属性
    • 元素节点的事件属性 el.onclick=function(){}
  • this的指向

    • 函数内部this指向当前元素节点
  • 事件的传播

    • 第一阶段:从window对象传导到目标节点(上层传到底层),称为“捕获阶段”(capture phase)
    • 第二阶段:从目标节点上触发,成为“目标阶段”(target phase)
    • 第三阶段:从目标节点传导回window对象(从底层传回上层),称为“冒泡阶段”(bubbling phase)

        

点击

bubbles

我们可以创建一个带有名称的冒泡事件并将其“hello”捕获document.
我们只需要设置bubblestrue


    

event.preventDefault()

在允许阻止默认事件cancelable: true条件下,如果设置event.preventDefault,dispatchEvent(event)会返回false,否则返回true

let event = CustomEvent('hide',{
    cancelabel : true    // 允许阻止默认事件,如果不设置event.preventDefault将无效
})
console.log(elem.dispatchEvent(event))    // false</code></pre>

其他

1.事件对象中的事件是同步的
2.new Event(),new MouseEvent()被叫做
3.我们不应该自己来生成浏览器事件,因为它是运行处理程序的一种hack方式。可能需要的地方:

  • 第三方库不提供其他交互方式
  • 自动化测试,要在脚本中“单机按钮”,看看界面是否正确反应
  • 具有我们自己名字的自定义事件通常是处于架构目的而生成的,用于表示我们的菜单,滑块,旋转木马等内部发生事件

鼠标事件

有时对滚动元素进行处理时,如果使用JavaScript来处理,请记住要处理的不是"scroll"事件,而是每当用户使用鼠标滚轮或触摸板时触发的"wheel"事件

下拉刷新

Loren Brichter - pull-to-refresh交互技术创建者
目前有个新草案:css通过overscroll-behavior这个新属性实现。

触摸事件

e.changedTouches.item(0)返回值:

  • identifier 表示触摸点的唯一ID
  • target 表示触摸点开始时所在的网页元素
  • clientX 表示触摸点相对于浏览器窗口左上角的水平距离
  • clientY 表示触摸点相对于浏览器窗口左上角的垂直距离
  • screenX 表示触摸点相对于屏幕左上角的水平距离
  • screenY 表示触摸点相对于屏幕左上角的垂直距离
  • pageX 表示触摸点相对于网页左上角的水平位置(即包括页面的滚动距离)
  • pageY 表示触摸点相对于网页左上角的垂直位置(即包括页面的滚动距离)
  • radiusX 表示触摸点周围受到影响的椭圆范围的X轴半径
  • radiusY 表示触摸点周围受到影响的椭圆范围的Y轴半径
  • rotationAngle 表示触摸区域的椭圆的旋转角度,单位为度数,在090度之间
  • force 表示触摸压力,在01之间。0代表没有压力,1代表硬件所能识别的最大压力
注意⚠️:这里的xy坐标系和数学中的直角坐标系x轴和y轴相反

实例属性

TouchEvent.changedTouches

  • touchstart
  • touchmove
  • touchend
  • touchcancel

requestAnimationFrame

特点

  • requestAnimationFrame会把每一帧的所有DOM操作集中起来,在一次重绘回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率
  • 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量
  • requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销

使用

setTimeout很相似,只是不需要设置时间间隔而已。
使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。它返回一个整数,表示定时器的编号,这个值可以传递个cancelAnimationFrame用于取消这个函数的执行。

setTimeout

requestAnimationFrame

兼容

IE9-浏览器不支持该方法,可以使用setTimeout来polyfill
简单兼容

严格兼容

if (!window.cancelAnimationFrame) {
    window.cancelAnimationFrame = function(id) {
        clearTimeout(id);
    };
}</code></pre>

函数节流 - throttle

使用场景

当用户高频率地滚动页面,滚动时间触发太频繁的话,会导致性能上的问题,可以通过使用函数节流这一技巧去优化它。

{
        // do sth
    }))

简单版

使用window.requestAnimationFrame()实现函数节流更加平滑;这里推荐一个

{
                action();
                isRunning = false;
            })
        }
    }

函数防抖 - debounce

防抖的原理就是:你尽管触发事件,但是我一定在事件触发 n 秒后才执行,如果你在一个事件触发的 n 秒内又触发了这个事件,那我就以新的事件的时间为准,n 秒后才执行,总之,就是要等你触发完事件 n 秒内不再触发事件,我才执行,真是任性呐! #摘自参考5
以下代码是卡动画防止在一帧时间中(大概16ms)渲染多次。

以下代码是表单验证时onkeyup非常适合使用防抖,等输入完后才进行验证