JS基础 事件

Posted wgchen~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS基础 事件相关的知识,希望对你有一定的参考价值。

阅读目录

基础知识

在文档、浏览器、标签元素等元素在特定状态下触发的行为即为事件,比如用户的单击行为、表单内容的改变行为即为事件,我们可以为不同的事件定义处理程序。JS使用异步事件驱动的形式管理事件。

事件类型
JS为不同的事件定义的类型,也可以称为事件名称。

事件目标
事件目标指产生事件的对象,比如 a 标签被点击那么 a 标签就是事件目标。
元素是可以嵌套的,所以在进行一次点击行为时可能会触发多个事件目标。

处理程序

事件的目的是要执行一段代码,我们称这类代码为事件处理(监听)程序。当在对象上触发事件时就会执行定义的事件处理程序。

html绑定

可以在html元素上设置事件处理程序,浏览器解析后会绑定到DOM属性中

<button onclick="alert(`wgchen.blog.csdn.net`)">博客地址</button>

往往事件处理程序业务比较复杂,所以绑定方法或函数会很常见

绑定函数或方法时需要加上括号

<button onclick="show()">博客</button>
<script>
  function show() 
    alert('wgchen.blog.csdn.net')
  
</script>

使用方法做为事件处理程序

<input type="text" onkeyup="HD.show()" />
<script>
  class HD 
    static show() 
      console.log('wgchen.blog.csdn.net')
    
  
</script>

传递事件源对象与事件对象

<button onclick="show(this,'wgchen','willem','博客',event)">技术文章</button>
<script>
    function show(...args) 
        console.log(args)
    
</script>

DOM绑定

也可以将事件处理程序绑定到DOM属性中

  • 使用 setAttribute 方法设置事件处理程序无效
  • 属性名区分大小写
<div id="app">wgchen.blog.csdn.net</div>
<script>
  const app = document.querySelector('#app')
  app.onclick = function () 
    this.style.color = 'red'
  
</script>


无法为事件类型绑定多个事件处理程序,下面绑定了多个事件处理程序,因为属性是相同的所以只有最后一个有效。

<div id="app">wgchen.blog.csdn.net</div>
<script>
  const app = document.querySelector('#app')
  
  app.onclick = function () 
    this.style.color = 'red'
  

  app.onclick = function () 
    this.style.fontSize = '55px'
  
</script>

事件监听

通过上面的说明我们知道使用HTML与DOM绑定事件都有缺陷,建议使用新的事件监听绑定方式 addEventListener 操作事件

使用 addEventListener 添加事件处理程序有以下几个特点

  • transtionend / DOMContentLoaded 等事件类型只能使用 addEventListener 处理
  • 同一事件类型设置多个事件处理程序,按设置的顺序先后执行
  • 也可以对未来添加的元素绑定事件
方法说明
addEventListener添加事件处理程序
removeEventListener移除事件处理程序

addEventListener 的参数说明如下

1、参数一事件类型
2、参数二事件处理程序
3、参数三为定制的选项,可传递 objectboolean 类型。后面会详细介绍使用区别

绑定多个事件

使用 addEventListener 来多个事件处理程序

<div id="app">wgchen.blog.csdn.net</div>
<script>
  const app = document.querySelector('#app')
  app.addEventListener('click', function () 
    this.style.color = 'red'
  )
  app.addEventListener('click', function () 
    this.style.fontSize = '55px'
  )
</script>

通过对象绑定

如果事件处理程序可以是对象,对象的 handleEvent 方法会做为事件处理程序执行。

下面将元素的事件统一交由对象处理

<div id="app">wgchen.blog.csdn.net</div>
<script>
  const app = document.querySelector('#app')
  class HD 
    handleEvent(e) 
      this[e.type](e)
    
    click() 
      console.log('单击事件')
    
    mouseover() 
      console.log('鼠标移动事件')
    
  
  app.addEventListener('click', new HD())
  app.addEventListener('mouseover', new HD())
</script>

移除事件

使用 removeEventListener 删除绑定的事件处理程序

事件处理程序单独定义函数或方法,这可以保证事件处理程序是同一个

<div id="app">wgchen.blog.csdn.net</div>
<button id="hd">删除事件</button>

<script>
  const app = document.querySelector('#app')
  const hd = document.querySelector('#hd')

  function show() 
    console.log('APP我执行了')
  

  app.addEventListener('click', show)
  
  hd.addEventListener('click', function () 
    app.removeEventListener('click', show)
  )
</script>

事件选项

addEventListener 的第三个参数为定制的选项,可传递 object 或 boolean 类型

下面是传递对象时的说明

选项可选参数
oncetrue/false只执行一次事件
capturetrue/false事件是在捕获/冒泡哪个阶段执行,true:捕获阶段 false:冒泡阶段
passivetrue/false声明事件里不会调用 preventDefault(),可以减少系统默认行为的等待

使用 once:true 来指定事件只执行一次

<div id="app">wgchen.blog.csdn.net</div>
<script>
  const app = document.querySelector('#app')
  app.addEventListener(
      'click',
      function () 
          alert('wgchen.blog.csdn.net@博客')
      ,
       once: true 
  )
</script>

设置 capture: true 或直接设置第三个参数为 true 用来在捕获阶段执行事件

addEventListener 的第三个参数传递 true/false 和设置 capture:true/false是一样

<div id="app" style="background-color: red">
    <button id="bt">wgchen.blog.csdn.net</button>
</div>
<script>
    const app = document.querySelector('#app')
    const bt = document.querySelector('#bt')
    app.addEventListener(
        'click',
        function () 
            alert('这是div事件 ')
        ,
         capture: true 
    )

    bt.addEventListener(
        'click',
        function () 
            alert('这是按钮事件 ')
        ,
         capture: true 
    )
</script>

设置 capture: false 或直接设置第三个参数为 false 用来在冒泡阶段执行事件

<div id="app" style="background-color: red">
    <button id="bt">wgchen.blog.csdn.net</button>
</div>
<script>
  const app = document.querySelector('#app')
  const bt = document.querySelector('#bt')
  app.addEventListener(
      'click',
      function () 
          alert('这是div事件 ')
      ,
       capture: false 
  )

  bt.addEventListener(
      'click',
      function () 
          alert('这是按钮事件 ')
      ,
       capture: false 
  )
</script>

事件对象

执行事件处理程序时,会产生当前事件相关信息的对象,即为事件对事。系统会自动做为参数传递给事件处理程序。

  • 大部分浏览器将事件对象保存到 window.event
  • 有些浏览器会将事件对象做为事件处理程序的参数传递

事件对象常用属性如下:

属性说明
type事件类型
target事件目标对象,冒泡方式时父级对象可以通过该属性找到在哪个子元素上最终执行事件
currentTarget当前执行事件的对象
timeStamp事件发生时间
x相对窗口的X坐标
y相对窗口的Y坐标
clientX相对窗口的X坐标
clientY相对窗口的Y坐标
screenX相对计算机屏幕的X坐标
screenY相对计算机屏幕的Y坐标
pageX相对于文档的X坐标
pageY相对于文档的Y坐标
offsetX相对于事件对象的X坐标
offsetY相对于事件对象的Y坐标
layerX相对于父级定位的X坐标
layerY相对于父级定位的Y坐标
path冒泡的路径
altKey是否按了alt键
shiftKey是否按了shift键
metaKey是否按了媒体键
window.pageXOffset文档参考窗口水平滚动的距离
window.pageYOffset文档参考窗口垂直滚动的距离

冒泡捕获

冒泡行为

标签元素是嵌套的,在一个元素上触发的事件,同时也会向上执行父级元素的事件处理程序,一直到HTML标签元素。

  • 大部分事件都会冒泡,但像 focus 事件则不会
  • event.target 可以在事件链中最底层的定义事件的对象
  • event.currentTarget == this 即当前执行事件的对象

以下示例有标签的嵌套,并且父子标签都设置了事件,当在子标签上触发事件是会冒泡执行父级标签的事件。

<style>
#app 
    background: #34495e;
    width: 300px;
    padding: 30px;

#app h2 
    background-color: #f1c40f;
    margin-right: -100px;

</style>

<div id="app">
<h2>https://wgchen.blog.csdn.net</h2>
</div>

<script>
const app = document.querySelector('#app')
const h2 = document.querySelector('h2')

app.addEventListener('click', (event) => 
    console.log(`event.currentTarget:$event.currentTarget.nodeName`)
    console.log(`event.target:$event.target.nodeName`)
    console.log('app event')
)

h2.addEventListener('click', () => 
    console.log(`event.currentTarget:$event.currentTarget.nodeName`)
    console.log(`event.target:$event.target.nodeName`)
    console.log(`h2 event`)
)
</script>

阻止冒泡

冒泡过程中的任何事件处理程序中,都可以执行 event.stopPropagation() 方法阻止继续进行冒泡传递。

  • event.stopPropagation() 用于阻止冒泡
  • 如果同一类型事件绑定多个事件处理程序 event.stopPropagation() 只阻止当前的事件处理程序。
  • event.stopImmediatePropagation() 阻止事件冒泡并且阻止相同事件的其他事件处理程序被调用。

下例中为 h2 的事件处理程序添加了阻止冒泡动作,将不会产生冒泡,也就不会执行父级中的事件处理程序了。

<style>
#app 
    background: #34495e;
    width: 300px;
    padding: 30px;

#app h2 
    background-color: #f1c40f;
    margin-right: -100px;

</style>

<div id="app">
<h2>wgchen.blog.csdn.net</h2>
</div>

<script>
const app = document.querySelector('#app')
const h2 = document.querySelector('h2')

app.addEventListener('click', (event) => 
    console.log(`event.currentTarget:$event.currentTarget.nodeName`)
    console.log(`event.target:$event.target.nodeName`)
    console.log('app event')
)

h2.addEventListener('click', (event) => 
    event.stopPropagation()
    console.log(`event.currentTarget:$event.currentTarget.nodeName`)
    console.log(`event.target:$event.target.nodeName`)
    console.log(`h2 event`)
)

h2.addEventListener('click', (event) => 
    console.log('h2 的第二个事件处理程序')
)
</script>

事件捕获

事件执行顺序为 捕获 > 事件目标 > 冒泡,在向下传递到目标对象的过程即为事件捕获。
事件捕获在实际使用中频率不高。

通过设置第三个参数为 true capture: true 在捕获阶段执行事件处理程序。

<style>
#app 
    background: #34495e;
    width: 300px;
    padding: 30px;


#app h2 
    background-color: #f1c40f;
    margin-right: -100px;

</style>

<div id="app">
    <h2>wgchen.blog.csdn.net</h2>
</div>

<script>
const app = document.querySelector('#app')
const h2 = document.querySelector('h2')

app.addEventListener(
    'click',
    (event) => 
        console.log('app event')
    ,
     capture: true 
)

h2.addEventListener('click', (event) => 
    console.log(`h2 event`)
)
</script>

事件代理

借助冒泡思路,我们可以不为子元素设置事件,而将事件设置在父级。
然后通过父级事件对象的 event.target 查找子元素,并对他做出处理。

  • 这在为多个元素添加相同事件时很方便
  • 会使添加事件变得非常容易

下面是为父级 UL 设置事件来控制子元素 LI 的样式切换。

<style>
.hd 
    border: solid 2px #ddd;
    background-color: red;
    color: white;

</style>

<ul>
    <li>https://wgchen.blog.csdn.net</li>
    <li>博客</li>
</ul>

<script>
'use strict'
const ul = document.querySelector('ul')
ul.addEventListener('click', () => 
    if (event.target.tagName === 'LI') event.target.classList.toggle('hd')
)
</script>

可以使用事件代理来共享事件处理程序,不用为每个元素单独绑定事件。

<ul>
    <li data-action="hidden">https://wgchen.blog.csdn.net</li>
    <li data-action="color" data-color="red">博客</li>
</ul>

<script>
class HD 
    constructor(el) 
        el.addEventListener('click', (e) => 
            const action = e.target.dataset.action
            this[action](e)
        )
    

    hidden() 
        event.target.hidden = true
    
    
    color() 
        event.target.style.color

以上是关于JS基础 事件的主要内容,如果未能解决你的问题,请参考以下文章

js事件委托

JS基础-防抖和节流

2017-06-02Jquery基础

js函数的节流和防抖

JavaScript 事件循环

2016年5月27日上午(妙味课堂js基础-3笔记一(事件))