JS-事件

188 阅读6分钟

01 事件流

  1. 事件冒泡概念
    事件开始从最具体的元素开始接受,逐级向上传播到较为不具体的文档
    如:div-body-html-document-window
  2. 事件捕获概念
    事件开始从较为不具体的文档开始接受,逐级向下传播到最具体的元素
    如:window-document-html-body-div

02 事件处理程序

  1. HTML事件处理程序
    例:在div元素里的事件属性调用函数
<div id="box" onclick:"test();"></div>

<script type='text/javascript'>
function test(){
    document.getElementById('box').innerHTML += '1';
    //点击这个div部分将会打印一个1
}

</script>
  1. DOM0级事件处理程序
<div id="box"><div>

<script type='text/javascript'>
var box = document.getElementById('box');
box.onclick = function(){
    this.innerHTML += 1;
}

//删除事件处理程序
box.onclick = null;

//缺点是会有覆盖现象
box.onclick = function(){
    this.innerHTML += 2;
}//这个会覆盖+=1

</script>

3.DOM2级事件处理程序(IE8不支持DOM2级事件处理程序)

<div id="box"><div>

//addEventListner(事件名,处理程序的函数,布尔值)
//布尔值默认为false 处于冒泡阶段,true为事件捕获阶段
//removeEventListner()

<script type='text/javascript'>
var box = document.getElementById('box');
box.addEventListner('click', function(){
    this.innerHTML +=1;
},false);
box.addEventListner('click', function(){
    this.innerHTML +=2;
},false);
//这种情况下1和2都会出来

//正确移除事件方式
function test(){
    this.innerHTML += 1 ;
}
box.addEventListner('click', test, false);
box.removeEventListner('click',text, false);

</script>

4.IE事件处理程序

//IE:attachEvent()添加事件监听者  detachEvent()移除
//用法与DOM2级事件处理程序大体一样
//事件名click要改成onclick 且没有布尔值
//函数里的this.innerHTML改成

兼容IE8与其他浏览器的方法(自己封装一个函数)

<div id="box"><div>
<script type='text/javascript'>

var box = document.getElementById('box');
addEvent(box,'click',function(){
    console.log(this.innerHTML);
})

function addEvent (target, eventType, handler){
    if(target.addEventListener){//是否有这个属性
        target.addEventListener(eventType, handler ,false);
    }else{
        target.attachEvent('on' + eventType, function(){
            handler.call(target);//call方法可以改变this指向
            //这里把指向从window改向了box
        });
    }
    
}
</script>

03 事件调用顺序

相同点

  1. 如果同时出现HTML事件处理程序和DOM0级事件处理程序,DOM0级事件处理程序会覆盖HTML事件处理程序

不同点

如果同时出现HTML、DOM0级、DOM2级、IE事件处理程序

  1. chorme,safari,FF浏览器以及IE11结果:DOM0级、DOM2级、IE
  2. IE9、10结果:DOM0级、DOM2级、IE
  3. IE8:DOM0级、IE

04 如何获取事件对象

<div id="box"><div>

<script type='text/javascript'>

window.onload = function(){
    var box = document.getElementById('box');
    //1.event对象是事件处理程序的第一个参数 
    //ie8不兼容 打印出来为undefined
    box.onclick = function(e){
        this.innerHTML = e;//打印出来mouseevent
    }
    
    //2.直接可以使用event变量 低版本火狐不兼容
    box.onclick = function(){
        this.innerHTML = event;
    }
    
    //3.兼容性写法
    box.onclick = function(e){
        e = e || window.event ;
        this.innerHTML = e;
    }
}

</script>

05 事件目标

currentTarget target srcElement

  1. currentTarge属性返回时间当前所在的节点,正在执行的监听函数所绑定的节点 基本=this
<ul id = "box">
    <li class="item">1</li>
    <li class="item">2</li>
</ul>

<script type='text/javascript'>
var box = document.getElementById('box');

box.onclick = function(){
    e = e || window.event;
    console.log(e.currentTarget);//打印的是ul标签
    
    var items = document.getElementTagName('li');
    
    itmes[0].innerHTML = e.currentTarget;//打印的是object HTMLUListElement
}
</script>
  1. target属性返回的是事件的实际目标对象不支持IE8
//点击li部分
box.onclick = function(){
    e = e || window.event;
    console.log(e.target);//打印的是li标签
    console.log(e.target===this);//打印的是false因为this指向ul标签
    
    //this对象跟e.currentTarget属性是一致的
    console.log(e.currentTarget===this);true
  1. srcElement 跟target方法一致 不支持低版本火狐
box.onclick = function(){
    e = e || window.event;
    console.log(e.srcElement);//打印的是li标签
}
  1. 兼容性代码
box.onclick = function(){
    e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
}

06 事件代理

//目的:鼠标移到li部分 li部分变色 移开鼠标 恢复原来颜色
<head>
    <style type="text/css">
    * {
      list-style: none;
    }

    li {
      float: left;
      width: 100px;
      height: 100px;
      text-align: center;
      line-height: 100px;
      color: red;
      background-color: black;
      margin: 0 10px;
    }
  </style>
</head>

<body>
  <ul id="box">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
  </ul>

  <script type='text/javascript'>
    
    //常规方法实现 1.获取标签
    var lis = document.getElementsByTagName('li');
    for (var i = 0; i < lis.length; i++) {
      lis[i].onmouseover = function () {
        this.style.backgroundColor = 'blue';
      }
      lis[i].onmouseout = function () {
        this.style.backgroundColor = 'black';
      }
    }
    
    //事件代理的方式实现
    //事件代理应用:事件实际目标对象target和srcElement属性完成
    //优点:提高性能以及降低代码复杂度 且未来添加的li标签也会生效
    var box = document.getElementById('box');
    box.onmouseover = function (e) {
      e = e || window.event;
      var target = e.target || e.srcElement;
      target.style.backgroundColor = 'blue';
    }
    box.onmouseout = function (e) {
      e = e || window.event;
      var target = e.target || e.srcElement;
      target.style.backgroundColor = "black";
    }
  </script>

07 事件冒泡

  1. bubble
<button id="btn" style="height: 30px;width:200px;">按钮</button>
  <input type="text" id="test">
  <script type="text/javascript">
  
    //1.bubbles 返回一个布尔值 表示当前时间是否会冒泡 只读
    //大部分事件都冒泡 focus blur scroll事件不会冒泡 false
    var btn = document.getElementById('btn');
    var test = document.getElementById('test');
    btn.onclick = function (e) {
      e = e || window.event;
      console.log(e.bubbles);//true
    }
    test.onfocus = function (e) {
      e = e || window.event;
      console.log(e.bubbles);//false
    }
    
  </script>
  1. stopPropagation()表示取消时间的进一步冒泡 无返回值 ie8不支持
  btn.onclick = function(e){
      e = e || window.event;
      e.stopPropagation();
    }
    document.body.onclick = function(e){
      e = e || window.event;
      console.log('body');//不会被打印出来
    }
    //但是无法阻止同一时间的其他监听函数被调用
    //如果有两个addEventListener 在第一个addEventListener添加stopPropagation()
    //第二个addEventListener一样会执行
  1. stopImmediatePropagation()可以组织其他监听函数被调用

  2. cancelBubble 阻止冒泡 可读写 默认为false

    btn.onclick = function (e) {
        e = e || window.event;
        e.cancelBubble = true;
    }
    document.body.onclick = function(e){
        e = e || window.event;
        console.log('body');//不会被打印出来
    }

小结:stopImmediatePropagation() stopPropagation()属性 IE8不支持

cancelBubble = true;全浏览器支持但是不是标准写法

  1. 兼容写法
btn.onclick = function(e){
    e = e || window.event;
    if(e.stopPropagation){//如果存在这个方法
        e.stopPropagation();
    }else{
        e.cancelBubble  = true;
    }
}

08 取消默认事件

//1.<a href="javascript:void(0);">111</a>//不会跳转页面
//2.<a href="javascript:;">111</a>
<a href = "#" id="box">111</a>

<script type="text/javascript">
var box = document.getElementById('box');
box.onclick = function(e){
    e = e || window.event;
    if(e.preventDefault){
        e.preventDefault();//不兼容ie8及以下
    }else{
        e.returnVaule = false;//不兼容ie8以上
    }
}
</script>
box.onclick = function(e){
    e = e || window.event;
    return false;

09 鼠标事件对象属性

//坐标位置

<head>
<style type="text/css">
    #box {
      height: 300px;
      width: 300px;
      background: red;
    }
</style>
</head>

<body>
  <div id="box"></div>
  <script type="text/javascript">

    var box = document.getElementById('box');
    box.onmousemove = function (e) {
      e = e || window.event;
      
      //clientX/Y和x/y:相对于浏览器的x轴y轴距离(浏览器的有效区域)
      this.innerHTML = `clinetX:${e.clientX};clinetY:${e.clientY};X:${e.x};Y:${e.y}`;
      
      //screenX/Y:相对于显示器屏幕的x轴和y轴的距离
      this.innerHTML = `screenX:${e.screenX};screenY:${e.screenY};`;
      
      //pageX/Y:相对于页面x轴和y轴的距离
      this.innerHTML = `pageX:${e.pageX};pageY:${e.pageY};`;
      
    //offsetX/Y:相对于事件源的x轴和y轴的距离
      this.innerHTML = `offsetX:${e.offsetX};offsetY:${e.offsetY};`;
    }

  </script>