Event事件对象2

事件监听器(事件绑定、事件侦听)

一个元素对象上面可以绑定多个事件处理函数,事件监听分为:标准浏览器事件监听、IE浏览器事件监听(非标准浏览器事件监听)

/*
    标准浏览器事件监听
    target.addEventListener("事件类型", 函数, 是否捕获(布尔值))
    是否捕获:默认不写就是冒泡(false) , true:捕获
*/

document.addEventListener('click', function () {
    console.log('事件绑定1');
}, false);

document.addEventListener('click', function () {
    console.log('事件绑定2');
}, false);

/*
    IE浏览器事件监听
    target.attachEvent("事件类型",函数)
*/
document.attachEvent('onclick', function() {
    alert('事件绑定1');
});

document.attachEvent('onclick', function() {
    alert('事件绑定2');
});

事件绑定:标准浏览器和非标准浏览器的区别

1.参数不一样。标准的三个参数,非标准的二个参数

2.事件类型不一样。标准不带on

3.执行顺序不一样。

4.this指向不一样,标准浏览器事件处理函数里面的this当前的操作的元素,但是非标准浏览器的this指向window

兼容解决事件绑定

function addEvent(obj, etype, fn) {
    if (obj.addEventListener) { //标准
        obj.addEventListener(etype, fn, false);
    } else {
        obj.attachEvent('on' + etype, fn);
    }
}

function fn1() {
    alert('兼容处理事件绑定1');
}
function fn2() {
    alert('兼容处理事件绑定2');
}
addEvent(document, 'click', fn1);
addEvent(document, 'click', fn2);

取消事件监听:参数和事件绑定的参数是一致的

target.removeEventListener()--标准浏览器取消监听

target.detachEvent() --IE浏览器取消监听

function removeEvent(obj, etype, fn) {
    if (obj.addEventListener) { //标准
        obj.removeEventListener(etype, fn, false);
    } else {
        obj.detachEvent('on' + etype, fn);
    }
}

removeEvent(document, 'click', fn1);
//取消事件绑定,不能取消匿名函数。

事件捕获

事件的第一个阶段是捕获阶段;事件从文档的根节点流向目标对象节点;途中经过各个层次的DOM节点,并在各节点上触发捕获事件,直到到达事件的目标节点;捕获阶段的主要任务是建立传播路径,在冒泡阶段,事件会通过这个路径回溯到文档跟节点。

<div class="big">
  <div class="middle">
      <div class="small"></div>
  </div>
</div>

比如上图的代码,三个div标签呈嵌套关系,假使三个元素都注册了相同的事件,那么他们的触发顺序是怎样的呢?

    <script src="./JS2004.js"></script>
    <script>
        //微软(microsoft) - 冒泡
        //网景(netscape) 捕获
        var small = $('.small');
        var middle = $('.middle');
        var big = $('.big');

        function fn() { //事件处理函数
            console.log(this.className);
        }

        function addEvent(obj, etype, fn, bool) {
            if (obj.addEventListener) { //标准
                obj.addEventListener(etype, fn, bool); //false:冒泡
            } else {
                obj.attachEvent('on' + etype, fn);
            }
        }

        //事件冒泡
        addEvent(small, 'click', fn, true); //目标
        addEvent(middle, 'click', fn, false);
        addEvent(big, 'click', fn, true);
        addEvent(document.body, 'click', fn, false);
        addEvent(document.documentElement, 'click', fn, true);
        addEvent(document, 'click', function () {
            console.log('我是document');
        }, false);
    </script>

结果如下:

事件委托:

事件委托:利用了冒泡原理,将子元素的事件委托给父元素

ev.target:获取当前操作的目标元素对象 标准的

        ev.srcElement:获取当前操作的目标元素对象  非标准的

使用下方案例说明事件委托:

HTML代码:

<body>
    <input type="text"><br>
    <button>创建li元素</button>
    <ul id="list">
    </ul>
</body>

CSS代码:

ul {
    margin: 0px;
    padding: 0px;
}

li {
    list-style: none;
    width: 600px;
    line-height: 24px;
    border: 1px dashed #ccc;
    padding: 10px;
    margin-top: 10px;
}

JS代码:

    <script>
        var oBtn = document.querySelector('button');
        var oText = document.querySelector('input');
        var oUl = document.querySelector('ul');

        //结构。
        oBtn.onclick = function () {
            var cLi = document.createElement('li');
            cLi.innerHTML = oText.value + '<a href="javascript:;">删除</a>';
            oUl.appendChild(cLi);
            oText.value = '';
        }

        //删除的逻辑 - 事件委托
        oUl.onclick = function (ev) {
            var ev = ev || window.event;
            var ele = ev.target || ev.srcElement; //获取当前操作的目标元素对象。
            if (ele.nodeName === 'A') {
                oUl.removeChild(ele.parentNode);
            }
        }
    </script>

事件委托的优缺点:

1.优点:减少事件注册,节约内存,提升性能 

        比如:如果不采用事件委托,内部的子元素采用遍历的方式逐个添加事件。 添加父元素解决这个问题。

2.缺点:所有事件都用事件代理,可能会出现事件误判。即本不该被触发的事件被绑定上了事件。

        比如:将所有的事件都绑定在document上面,所有的document内部的子元素事件都有可能触发到document上面。

事件冒泡需要时间类型一致

猜你喜欢

转载自blog.csdn.net/qq_39264561/article/details/107165911