JavaScript DOM 高级事件绑定和事件委托

目录

 HTML DOM 事件

1.事件对象

鼠标事件onmousedown对象

键盘事件对象

 例子:按键盘移动div

2.事件绑定及移除

事件绑定

DOM0级

DOM2级

事件移除

DOM0级

DOM2级

 事件流

4.阻止事件冒泡

5.阻止默认行为

事件委托

实现思路

概念

模拟搜索框


 HTML DOM 事件

  HTML DOM 允许 JavaScript 对 HTML 事件作出反应: JavaScript 能够在事件发生时执行,比如    当用户点击某个 HTML 元素时。

   HTML 事件的一些例子:

  • 当用户点击鼠标时
  • 当网页加载后
  • 当图像加载后
  • 当鼠标移至元素上时
  • 当输入字段被改变时
  • 当 HTML 表单被提交时
  • 当用户敲击按键时 

1.事件对象

  • 事件对象就是当前事件触发的详细信息,浏览器会将这些信息以一个对象的形式当做实参传递给事件处理函数的第一个形参

  • 事件对象也会存储在浏览器顶层对象中 window.event

鼠标事件onmousedown对象

//直接给文档绑定
document.onmousedown = function (event) {
    // event:IE8及以下不兼容  浏览器没有传递实参 默认值是undefined
    // 事件对象的兼容处理  
    event = event || window.event;
    console.log(event);

    // 事件对象的属性
    //target 事件源  事件触发的源头   
    // 不兼容 IE8及以下没有这个属性
    // 兼容处理
    var target = event.target || event.srcElement;
    console.log(target);

    // 事件类型
    // type
    console.log(event.type);

    // 位置属性
    // clientX  / clientY  距离可视区域左上角距离
    console.log(event.clientX, event.clientY);

    // pageX / pageY  距离文档(body)的距离 
    // IE8及以下不兼容  没有这个属性
    console.log(event.pageX, event.pageY);  

    // screenX / screenY  距离电脑屏幕(左上角)的距离
    console.log(event.screenX, event.screenY);


    // altKey / ctrlKey / shiftKey    当前事件触发是否按下了对应的键 默认值都是flase,按下了值为true
    console.log(event.altKey, event.ctrlKey, event.shiftKey);
    if (event.altKey) {
        console.log("hello");
    }

键盘事件对象

  • onkeydown :键盘按下

  • onkeypress:键盘按着

  • onkeyup:键盘抬起

键盘事件一般给document 或 表单输入框  

target 事件源  事件触发的源头 

document.onkeydown = function (ev) {
    // 事件对象兼容处理
    // event:IE8及以下不兼容  浏览器没有传递实参 默认值是undefined
    ev = ev || window.event;
    console.log(ev); //KeyboardEvent{...}

    // 事件对象的属性
    //target 事件源  事件触发的源头   
    // 不兼容 IE8及以下没有这个属性
    // 兼容处理
    var target = ev.target || ev.srcElement;
    console.log(target);

    // key 键值  不兼容IE8及以下没有这个属性
    console.log(ev.key);

    // keyCode 键盘码  ASCII值
    // onkeydown 和 onkeyup 不区分大小写 都是大写的ASCII值  onkeypress区分大小写
    console.log(ev.keyCode);

    // altKey / ctrlKey / shiftKey    当前事件触发是否按下了对应的键 默认值都是flase,按下了值为true
    console.log(ev.altKey, ev.ctrlKey, ev.shiftKey);
    if(ev.keyCode == 66 && ev.altKey){
        console.log("alt + b");
    }


    // type  事件类型
    console.log(ev.type);

}

 例子:按键盘移动div

 <div></div>
    <script>
        var div = document.getElementsByTagName("div")[0];

        // 绑定键盘事件
        document.onkeydown = function(ev){
            // 事件对象兼容处理
            ev =ev || window.event;

            console.log(ev.keyCode);

            //w:87
            //s:83
            //a:65
            //d:68
            if(ev.keyCode == 87){
                div.style.top = parseFloat(getComputedStyle(div).top) - 10 + 'px';
            }else if(ev.keyCode == 83){
                div.style.top = parseFloat(getComputedStyle(div).top) + 10 + 'px';
            }else if(ev.keyCode == 65){
                div.style.left = parseFloat(getComputedStyle(div).left) - 10 + 'px';
            }else if(ev.keyCode == 68){
                div.style.left = parseFloat(getComputedStyle(div).left) + 10 + 'px';
            }
        }
    </script>

2.事件绑定及移除

事件绑定

DOM0级

  • 语法:元素.on事件类型 = 函数;

  • 特性:一个事件只能对应一个事件处理函数,赋值多个后边赋值的副高前边的

document.onclick = function () {
    console.log("点我啊1");
}
document.onclick = function () {
    console.log("点我啊2");
}

DOM2级

  • 语法:元素.addEventListener(eventType,callBack,[false]);

    • eventType:事件类型

    • callBack:函数,做的事情,事件处理函数

    • [false]  默认值false 可以省略 控制当前事件出函数在那个阶段调用,false在冒泡阶段,true在捕获阶段

  • 特性:一个事件可以对应多个事件处理函数,不会覆盖

document.addEventListener("click",function(){
    console.log("hello");
});

document.addEventListener("click",function(){
    console.log("world");
});
  • 不兼容IE8及以下

    • IE下提供DOM2级事件绑定独有的方法

    • 语法:元素.attachEvent(on事件类型,callBack);

document.attachEvent("onclick",function(){
    console.log("哈哈");
});

document.attachEvent("onclick",function(){
    console.log("呵呵");
});
  • 兼容处理

function test(){
    console.log("哈哈");
}

function test1(){
    console.log("呵呵");
}

/*
   作用: DOM2级事件绑定兼容处理
   参数:
    eleObj:元素
    eventType:事件类型
    callBack:做的事情
*/

function eventBind(eleObj,eventType,callBack){
    if(eleObj.addEventListener){//标准浏览器
        eleObj.addEventListener(eventType,callBack);
    }else{//IE8及以下
        eleObj.attachEvent("on"+eventType,callBack);
    }
}

eventBind(document,"mousedown",test);
eventBind(document,"mousedown",test1);

事件移除

DOM0级

  • 基本语法:元素.on事件类型 = null;

var box = document.getElementById("box");
box.onmousedown = function () {
    console.log("鼠标按下");
    // 事件移除
    box.onmousedown = null;
}

DOM2级

  • 基本语法:元素.removeEventListener(eventType,callBack,[false]);

    • eventType:事件类型

    • callBack:函数 实名函数

    • false 默认值false 可以省略

      • 可以省略 控制当前事件出函数在那个阶段移除,false在冒泡阶段,true在捕获阶段

  • 不兼容IE8及以下

    • IE下提供了独有的DOM2级事件移除的方法

    • 基本语法:元素.detachEvent(on事件类型,callBack);

  • 兼容处理

/* 
    作用:DOM2级事件移除兼容处理
    参数:
        eleObj:元素
        eventType:事件类型
        callBack:做的事情

*/
function unEventBind(eleObj,eventType,callBack){
    if(eleObj.removeEventListener){ //标准浏览器
        eleObj.removeEventListener(eventType,callBack);
    }else{//IE8及以下
        eleObj.detachEvent("on"+eventType,callBack);
    }
}

 事件流

 事件流又称为事件传播机制,描述了事件传递的过程,可以分为以下3个阶段:

事件处理函数默认都是在冒泡阶段调用的

  • CAPTURING_PHASE: 1 捕获阶段

    • 当前事件触发从window依次向内查找事件源的过程

  • AT_TARGET: 2 目标阶段

    • 找到事件源,事件触发的源头

  • BUBBLING_PHASE: 3 冒泡阶段 bubbing_ph

    • 将当前事件对应的事件处理函数触发,依次向外进行传递,也将父级当前事件对应的事件处理函数触发

4.阻止事件冒泡

  • ev.stopPropagation();在IE8及以下没有这个属性

  • 兼容处理: ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;

 box.onclick = function (ev) {
            ev = ev || window.event;
            // 阻止事件冒泡
            //  ev.stopPropagation();在IE8及以下没有这个属性
            ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;
            console.log("box");
        }

5.阻止默认行为

  • ev.preventDefault(); 阻止默认行为,不兼容,兼容处理

  • 兼容处理: ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;

  <a href="">点我啊</a>
    <script>
        var a = document.getElementsByTagName("a")[0];

        a.onclick = function (ev) {
            // 事件对象兼容处理
            ev = ev || window.event;
            // 阻止默认行为,不兼容,兼容处理
            ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;

            console.log("哈哈");
        }


        // 鼠标右击
        document.oncontextmenu = function (ev) {
            // 事件对象兼容处理
            ev = ev || window.event;
            // 阻止默认行为,不兼容,兼容处理
            ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
            console.log("oncontextmenu");
        }
    </script>

事件委托

将共同事件委托给它们共同父级,事件委托的本质就是利用事件冒泡

实现思路

概念

  当一个父元素中所有的子元素都拥有相同的事件行为的时候,可以根据DOM事件流中的冒泡原

理,让所有的子元素将自身的事件行为向上传递给其直接父元素,让直接父元素发生事件,好处是在后期添加新的子元素的时候,也同样拥有之前的事件行为

实现思路:

  • 1、给父元素添加事件行为
  • 2、在嵌套类布局中找到实际发生事件的子元素(兼容的事件对象.target || 兼容的事件对
  • 象.srcElement)
  • 3、获取到实际发生的子元素进行后续的操作
  • 3-1 如果拿到的子元素节点类型不统一,可以按照节点名称nodeName来进行区分
  • 3-2 如果拿到的子元素统一,还可以根据值、样式、属性等进行区分
 // 将共同事件委托给它们共同父级,事件委托的本质就是利用事件冒泡
        ul.onclick = function (ev) {
            // 事件对象兼容处理
            ev = ev || window.event;
            // 事件源
            var target = ev.target || ev.srcElement;

            console.log(target);
            //判断事件源  ->具体的元素    nodeName:节点名称->大写的标签名
            if (target.nodeName.toLowerCase() == "li") {
                target.style.backgroundColor = "red";
            }

            if (target.nodeName == "P") {
                target.style.backgroundColor = "yellow";
            }
        }

模拟搜索框

 <div id="search">
        <input type="text" class="searchText" />
        <ul class="searchList">
            <li>HTML</li>
            <li>CSS</li>
            <li>JavaScript</li>
        </ul>
    </div>

    <script>
        // 获取元素
        var search = document.querySelector("#search"),
            searchText = search.querySelector(".searchText"),
            searchList = search.querySelector(".searchList");
        // 绑定事件
        searchText.onclick = function (ev) {
            // 事件对象兼容处理
            ev = ev || window.event;
            // 阻止事件冒泡
            ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;
            // 展示ul
            searchList.style.display = "block";
        }

        // 事件委托
        document.onclick = function (ev) {
            // 事件对象兼容处理
            ev = ev || window.event;
            // 事件源兼容处理
            var target = ev.target || ev.srcElement;
            console.log(target);

            // 判断点击的是searchList下的li
            if (target.nodeName.toLowerCase() == "li" && target.parentNode.className == "searchList") {
                // 将li的内容赋值给输入框
                searchText.value = target.innerText;
            }

            // 隐藏ul
            searchList.style.display = "none";
        }
    </script>

猜你喜欢

转载自blog.csdn.net/weixin_58139900/article/details/121201129