DOM事件

作者: 好奇男孩 | 来源:发表于2018-03-25 10:36 被阅读4次

1.事件

JavaScript和HTML的交互是通过事件实现的。JavaScript采用异步事件驱动编程模型,当文档、浏览器、元素或与之相关对象发生特定事情时,浏览器会产生事件。如果JavaScript关注特定类型事件,那么它可以注册当这类事件发生时要调用的句柄:
如事件是某个行为或者触发,比如点击、鼠标移动;当用户点击鼠标时;当网页已加载时

DOM2事件传播机制

当事件发生在某个文档节点上时(即事件目标),目标的事件处理程序就会被触发。此外目标的每个祖先节点也有机会处理该事件。
2级DOM的事件传播包含三个阶段:
1.事件捕捉阶段(capturing),事件具体的节点更早接收事件,而最具体的元素最后接收事件;从顶级文档树节点一级一级向下遍历,直到到达该事件的目标节点。
2.到达事件的目标节点,执行目标节点的时间处理程序。
3.事件冒泡(bubbling),事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的元素;从目标节点一级一级向上上溯,直到顶级文档树节点

<!DOCTYPE html >
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <title>Test Page</title>
</head>
<body>
    <div>
        Click Here</div>
</body>
</html>
1.png

事件冒泡模型


2.png

事件捕获模型


3.png
DOM事件流
<style>
    .container,
    .box,
    .target{
      border: 1px solid;
      padding: 10px;
    }  
  </style>
  <button id="btn">click</button>

  <div class="container">
    container
    <div class="box">
      box
      <div class="target">target</div>
    </div>
  </div>

  <script>

  function $(selector){
    return document.querySelector(selector)
  }

  var btn = $('#btn')
  btn.onclick = function (e){
   console.log(e) 
  }
  btn.addEventListener('click', function(evt){
    console.log(this)
    console.log(btn)
    console.log(evt.target)
  })

  $('.container').addEventListener('click', function(e){
    console.log('contianer click.. in 捕获阶段')
  }, true)
  $('.box').addEventListener('click', function(e){
    console.log('box click.. in 捕获阶段')
  }, true)
  $('.target').addEventListener('click', function(e){
    console.log('target click.. in 捕获阶段')
  }, true)

  $('.container').addEventListener('click', function(e){
    console.log('contianer click.. in 冒泡阶段')
  }, false)
  $('.box').addEventListener('click', function(e){
    console.log('box click.. in 冒泡阶段')
  }, false)
  $('.target').addEventListener('click', function(e){
    console.log('target click.. in 冒泡阶段')
  }, false)    


  </script>
4.png

DOM2事件处理程序

DOM2级事件定义了两个方法用于处理指定和删除事件处理程序的操作:
1.addEventListener
2.removeEventListener
所有的DOM节点都包含这两个方法,并且它们都接受三个参数:
事件类型
事件处理方法
布尔参数,如果是true表示在捕获阶段调用事件处理程序,如果是false,则是在事件冒泡阶段处理

    var ul=document.querySelector('.ct');
    ul.addEventListener('click',function(e){
        console.log(e.target.innerText);
    });

阻止默认事件:

preventDafault方法取消浏览器对当前事件的默认行为,比如点击链接后,浏览器跳转到指定页面,或者按一下空格键,页面向下滚动一段距离。该方法生效的前提是,事件的cancelable属性为true如果为fales,则调用该方法没有任何效果。
比如我们可以阻止链接导航这一默认行为

<a href="http://baid.com">baidu</a>
<script>
  document.querySelector('a').onclick= function(e){
    e.preventDefault()
    console.log(this.href)
    if(/baidu.com/.test(this.href)){
      location.href = this.href
    }
  }
</script>

阻止传播

stopPropagation方法阻止事件在DOM中继续传播,即取消进一步的事件捕获或冒泡,防止再触发定义在别的节点上的监听函数,但是不包括在当前节点上新定义的事件监听函数。
我们可以在button的事件处理程序中调用stopPropagation()从而避免注册在body上的事件发生

<style>
    .container,
    .box,
    .target{
      border: 1px solid;
      padding: 10px;
    }  
  </style>
  <button id="btn">click</button>

  <div class="container">
    container
    <div class="box">
      box
      <div class="target">target</div>
    </div>
  </div>

  <script>

  function $(selector){
    return document.querySelector(selector)
  }

  var btn = $('#btn')
  btn.onclick = function (e){
   console.log(e) 
  }
  btn.addEventListener('click', function(evt){
    console.log(this)
    console.log(btn)
    console.log(evt.target)
  })

  $('.container').addEventListener('click', function(e){
    console.log('contianer click.. in 捕获阶段')
  }, true)
  $('.box').addEventListener('click', function(e){
    console.log('box click.. in 捕获阶段')
  }, true)
  $('.target').addEventListener('click', function(e){
    console.log('target click.. in 捕获阶段')
  }, true)

  $('.container').addEventListener('click', function(e){
    console.log('contianer click.. in 冒泡阶段')
  }, false)
  $('.box').addEventListener('click', function(e){
    e.stopPropagation();
    console.log('box click.. in 冒泡阶段')
  }, false)
  $('.target').addEventListener('click', function(e){
    console.log('target click.. in 冒泡阶段')
  }, false)    


  </script>

5.png

范例:
1.点击按钮会弹出面板
2.点击面板列表会在标题展示点击的内容
3.点击面板以外的区域面板会消失

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <style>
    section {
      width: 800px;
      margin: 0 auto;
      position: relative;
    }
    ul,li {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .card {
      position: absolute;
      border: 1px solid #ccc;
      width: 200px;
      display: none;
    }
    .card li {
      border-bottom: 1px solid #ccc;
      padding: 10px;
      cursor: pointer
    }
  
  </style>
</head>
<body>
  <section>
    <h1>你选择了 <span class="choice"></span></h1>
    <button class="btn">点我</button>
    <ul class="card">
      <li>菜单1</li>
      <li>菜单2</li>
      <li>菜单3</li>
    </ul>
  </section>
  
  <script>
    let choice = document.querySelector('.choice')
    let btn = document.querySelector('.btn')
    let card = document.querySelector('.card')
    let items = document.querySelectorAll('.card li')
    
    btn.onclick = function(e) {
       card.style.display = "block"
       e.stopPropagation()
    }
    
    items.forEach(item => {
      item.onclick = function(e) {
        choice.innerText = this.innerText
        e.stopPropagation()
      }
    })
    
    document.onclick = function() {
      card.style.display = "none"
    }
    
    
    
  </script>
</body>
</html>

效果:http://js.jirengu.com/jebew

事件代理

由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理
定义:事件代理就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。(delegation)。

var ul = document.querySelector('ul');
ul.addEventListener('click', function(event){
    if(event.target.tagName.toLowerCase() === 'li'){
        //...
    }
})

范例1:
当点击li的时候会在console.log打印输出

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<ul class="ct">
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
<script>
    var ul=document.querySelector('.ct');
    ul.addEventListener('click',function(e){
       console.log(e.target.innerText);//"1"
        console.log(this.innerText) //" 1 2 3"
    });
</script>
</body>
</html>

范例2:
1.当勾选 checkbox 时, 标题的我要学后要展示对应勾选的内容
2.当新增标签后,可勾选新增的标签,切勾选后仍展示到标题上

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title></title>
</head>
<body>
  <h1>我要学<span class="txt">____</span></h1>
  <ul class="box">
    <li>前端 <input type="checkbox" value="前端"></li>
    <li>Java <input type="checkbox" value="Java"></li>
    <li>PHP <input type="checkbox" value="PHP"></li>
  </ul>
  <div>
    <input type="text" class="ipt"> <button class="add"> 新增</button>
  </div>
  <script>
    let  checkboxs = document.querySelectorAll('.box [type=checkbox]')
    let addBtn = document.querySelector('.add')
    let text = document.querySelector('.txt')
    let input = document.querySelector('.ipt')
    let box = document.querySelector('.box')
    let values = []
      
    addBtn.onclick = function() {
      let node = document.createElement('li')
      node.innerText = input.value
      let checkbox = document.createElement('input')
      checkbox.type = "checkbox"
      checkbox.value = input.value
      box.appendChild(node)
      node.appendChild(checkbox)
      
    }
    box.onclick = function(e) {
      console.log(e.target.value)
        text.innerText = e.target.value
      //添加所有选中元素
//       text.innerText = [...document.querySelectorAll('.box [type=checkbox]')].filter(checkbox=>checkbox.checked)
//            .map(checkbox=>checkbox.value).join(',')
    }
  </script>
</body>
</html>

效果:http://js.jirengu.com/baqul

注意:使用事件代理(委托),之后,要有效的操作实际触发的dom节点,可使用.target方法,而不能用this,在这里this指绑定事件的元素,而不是实际触发的元素;

作用:以后再添加子节点,监听函数依然有效

自定义事件

var EventCenter = {
  on: function(type, handler){
    document.addEventListener(type, handler)
  },
  fire: function(type, data){
    return document.dispatchEvent(new CustomEvent(type, {
      detail: data
    }))
  }
}

EventCenter.on('hello', function(e){
  console.log(e.detail)
})

EventCenter.fire('hello', '你好')

作者:彭荣辉
链接:https://www.jianshu.com/u/0f804364a8a8
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关文章

  • 前端面试题(3)——DOM事件类

    基本概念:DOM事件的级别 DOM事件模型:事件冒泡事件捕获 DOM事件流 描述DOM事件捕获的具体流程 Even...

  • DOM事件

    DOM级别与DOM事件 DOM级别:DOM0级、DOM1级、DOM2级、DOM3级DOM事件:DOM0级事件处理、...

  • DOM事件

    DOM级别与DOM事件 DOM级别:DOM0级,DOM1级,DOM2级和DOM3级DOM事件:DOM0级事件处理,...

  • DOM0和DOM2级事件简单理解

    关于DOM0 和DOM1级事件可以简单理解为:事件分为DOM 0级事件和Dom 2级事件,DOM2级事件也叫做事件...

  • Dom事件

    基本概念 Dom事件级别 Dom事件模型 Dom事件流 描述Dom事件捕获的具体流程 Event对象的常见应用 自...

  • 3-6 DOM事件

    问题 DOM 事件的级别 DOM 事件模型(就是捕获和冒泡儿) DOM 事件流 描述DOM事件捕获的具体流程 Ev...

  • HTML DOM 事件

    HTML DOM 事件 HTML DOM 事件 HTML DOM 事件允许Javascript在HTML文档元素中...

  • 网易微专业-DOM编程艺术 05 事件

    1、DOM事件⑴主要内容▪事件流▪事件注册▪事件对象▪事件分类▪事件代理 ⑵什么是DOM事件▪点击一个DOM元素▪...

  • DOM事件类

    基本概念:DOM事件的级别 DOM事件模型 DOM事件流 描述DOM事件捕获的具体流 Event对象的常见应用 自...

  • DOM事件

    DOM事件的级别 DOM事件模型 DOM事件流 描述DOM时间捕获的具体流程 Event对象的常见应用 自定义事件...

网友评论

    本文标题:DOM事件

    本文链接:https://www.haomeiwen.com/subject/rhrhcftx.html