美文网首页
JavaScript DOM Events

JavaScript DOM Events

作者: Qingelin | 来源:发表于2019-08-24 22:05 被阅读0次

DOM Events —— Document Object Model Events
我们目前用的DOM Level Event 是2000年11月13日发布的DOM Level 2,DOM Level 3并没有改动。

李爵士发明的第一个网页、第一个浏览器当时除了他没有人用,之后网景(Netscape)公司发布了Navigator浏览器,之后微软推出IE浏览器名叫Edge,由于商业竞争,网景公司更新了浏览器,改名为Firefox,这两家公司各用各的,没有统一标准,其实两者互相抄袭,为了使浏览器事件统一起来,W3C把两家公司的DOM事件综合起来发布了DOM Level 1,在此之前使用的DOM Events统称为DOM Level 0;目前已经更新到DOM Level 3;DOM Level 4在做草案阶段;(google(2009年)很久之后才推出,目前远超另外两个),因此互联网的无烟战争一直持续到现在。其实DOM Level 1只是一个汇总而已,而且也没把DOM Events分开为一个章节,到DOM Level 2才有了很大的突破,把DOM Events单独介绍,而且添加了很多功能。


DOM Level 0主要事件:

      <!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <script>
    function print(){
      console.log("hi")
    }
  </script>
</head>
<body>
      <button id="X" onclick="print">这个是错的</button>
      <button id="Y" onclick="print()">这个是对的</button>
      <button id="Z" onclick="print.call()">这个是对的</button>
 //以上三行代码中onclick=后必须加字符串,简单说就是要加括号
  
  
  <script>
      X.onclick = print  //这个是对的,类型为函数对象
      Y.onclick = print()   //这个是错的,返回undefined
      Z.onclick = print.call()  //这个是错的,返回undefined
     //以上三行代码中onclick=后必须加字符串,简单说就是js里面不加括号
  </script>
  
 //(html里面写的)onclick="要执行的代码"
  用户一旦点击浏览器就eval("要执行的代码"),
  所以onclick="print"什么也不做,        onclick="print()"/onclick="print.call()"调用上面的函数
  
  //(第二种js里面写的写的)一旦用户点击那么浏览器就执行 X.onclick.call(X,{})  所以:
  X.onclick = print  //这个是对的
  Y.onclick = print()   //这个是对的
  Z.onclick = print.call()  //这个是对的
</body>
</html>

DOM Level 2主要事件:

  1. onclick 和 addEventListener('click')的区别:实际当中使用addEventListener('click')
    //事件监听队列
    //xxx拥有一个EventListeners队列
    xxx.addEventListener('click', function(){
        console.log(1)
    })

    //onclick只是属性而已,一个元素只有一个属性,xxx只有一个onclick属性,不同于EventListener
     xxx.onclick = function(){
         console.log(2)
     }
  1. .addEventListener('click')本质上是队列,先进先出:
    //进队列
function f1(){
  console.log(1)
}
function f2(){
  console.log(2)
}
function f3(){
  console.log(3)
}

//添加事件监听
xxx.addEventListener('click',f1)
xxx.addEventListener('click',f2)


//出队列
xxx.removeEventListener('click',f1)
xxx.removeEventListener('click',f2)
xxx.addEventListener('click',f3)

//最后结果只打印 3
  1. one('事件名',函数名) 是一次事件监听函数,他用到的原理也是队列:下面的两个例子等价
      //函数f1入队、执行完了立即出队,只能执行一次
      function f1(){
        console.log(1)
        xxx.removeEventListener('click',f1)
      }
// 1

function f1(){
        console.log(1)
}
xxx.one('click',f1)
  1. 事件模型://w3c规定没有规定顺序,函数最后给一个falsy值就是从小到大顺序执行,给true就会从大到小顺序执行。不写默认falsy值。如果不是同一个元素,就跟代码顺序没有关系;
    DOM Level 2有两个概念:
    捕获阶段 —— (true)从爷爷到儿子顺序执行
    冒泡阶段 —— (false)反方向
      <div id="grandpa1">爷爷
        <div id="parent1">
            父亲
          <div id="child1">
              儿子
          </div>
       </div>
    </div>

    <script>
           grandpa1.addEventListener('click',function fn1(){
                  console.log('爷爷')
          },参数)
          parent1.addEventListener('click',function fn2(){
              console.log('爸爸')
          },参数)
          child1.addEventListener('click',function fn3(){
                  console.log('儿子')
          },参数)
    </script>
事件监听模型.png
  1. 1事件模型【面试题】:有捕获阶段,又有冒泡阶段则执行顺序:
  • 如果点的是该元素,则会按代码顺序执行
  • 如果点的是该元素的子级元素,会先执行捕获阶段,在执行冒泡阶段
      //以下代码点击child1元素会按代码顺序执行
       child1.addEventListener('click',function fn3(){
                  console.log('儿子捕获')
        },true)
       child1.addEventListener('click',function fn3(){
                  console.log('儿子冒泡')
        },falsy值)
      //以下代码点击grandpa1元素会按代码顺序执行
      //但是点击其它子元素会先执行捕获阶段,在执行冒泡阶段
       grandpa1.addEventListener('click',function fn3(){
                  console.log('儿子捕获')
        },true)
       grandpa1.addEventListener('click',function fn3(){
                  console.log('儿子冒泡')
        },falsy值)

4.2 事件模型使用实例 —— popover

      1. 事件监听:点击别处关闭浮层新手容易踩的坑
            btn.addEventListener("click", function(){
                  popover.style.display = "block"
            })

        //监听html或文档都可以,但是监听body的话范围太小
            document.addEventListener("click", function(){
                 popover.style.display = "none"
            })
          //这种方法实现点击btn出现浮层,点击别处消失是不能实现的,原因:一次点击btn,事件冒泡阶段,首先执行第一个函数dispaly:block,马上再执行第二个函数display:none;所以点击之后没有动静。

解决方法一:(如果浮层中没有其它按钮这个方法就是终极方案)中断事件冒泡

    btn.addEventListener("click", function(){
              popover.style.display = "block"
        },false)
        wrapper.addEventListener('click', function(e){
              e.stopPropagation()   //停止传播
        })
        document.addEventListener("click", function(){
               popover.style.display = "none"
        },false)

解决方法二:

  $(btn).on("click", function(){
          $(popover).show()
  })
   $(document).one("click", function(){
                  $(popover).hide()
   })
   $(wrapper).on("click",function(e){
          e.stopPropagation()
    })

解决方法二之新手经常踩的坑(错误):(节省内存)

   $(btn).on("click", function(){
          $(popover).show()
          $(document).one("click", function(){
                  $(popover).hide()
           })
    })

解决方法二新手经常踩的坑(错误).png

解决方法二之新手经常踩的坑(错误)之解决方案一:

   $(btn).on("click", function(){
          $(popover).show()
          $(document).one("click", function(){
                  $(popover).hide()
          })
  })
  $(wrapper).on("click",function(e){
          e.stopPropagation()
  })
//直接加上监听,但是阻止事件冒泡(父级部分中依然有调用函数,但已被阻止)

解决方法二之新手经常踩的坑(错误)之解决方案二:

    //让父级部分中存在的调用函数过段时间再执行
  $(btn).on('click', function(){
  $(popover).show()
  console.log("show")
  setTimeout(function(){
    console.log("添加one click")
    $(document).one('click', function(){
      $(popover).hide()
      console.log("内存中已有调用函数,但第一次不会执行,第二才会执行")
    })
  },0)
})


$(document).on('click',function(){
  console.log("click事件走到了这里")
})


最后代码优化:

  1. 点击按钮弹出浮层
  2. 点击别处关闭浮层
  3. 点击浮层时,浮层不得关闭
  4. 再次点击按钮,浮层消失
  document.addEventListener('click',function(){
        popover.classList.remove('active');
   });

   $('#btn').on('click',function(e){
       popover.classList.toggle('active');
   });

   $('#wrapper').on('click',function(e){
       e.stopPropagation();
   });

相关文章

网友评论

      本文标题:JavaScript DOM Events

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