(九)JavaScript——DOM之事件

1、元素绑定事件
(1)GlobalEventHandlers.eventType
	element.onclick = functionRef;

   全局事件处理器(GlobalEventHandlers)的 eventType 属性,是处理当前元素的 eventType 事件的事件处理器(EventHandler)。

  • functionRef:一个函数名称,或一个函数表达式。该函数接收 MouseEvent 对象作为其唯一参数。在函数内,this 是触发当前事件的元素。
(2)EventTarget.addEventListener()
	target.addEventListener(type, listener[, options]);
	target.addEventListener(type, listener[, useCapture]);
	// Gecko/Mozilla only
	target.addEventListener(type, listener[, useCapture, wantsUntrusted ]);  

   将指定的监听器注册到 EventTarget 上,当该对象触发指定的事件时,指定的回调函数就会被执行。 事件目标可以是一个文档上的元素 Element,Document和Window或者任何其他支持事件的对象 (比如 XMLHttpRequest)。

  • type:表示监听事件类型的字符串;
  • listener:当所监听的事件类型触发时,会接收到一个事件通知(实现了 Event 接口的对象)对象。listener 必须是一个实现了 EventListener 接口的对象,或者是一个函数;
  • options:可选,一个指定有关 listener 属性的可选参数对象;
  • useCapture:可选,指定需要移除的 EventListener 函数是否为捕获监听器。如果无此参数,默认值为 false;
  • wantsUntrusted :可选,如果为 true , 则事件处理程序会接收网页自定义的事件。
(3)绑定事件的兼容代码

   封装事件绑定函数,兼容不同的浏览器(有些浏览器不支持addEventListener(),而使用的是attachEvent(),比如IE8)。

<body>
    <input type="button" value="btn" id="btn">

    <script>
        function addEventListener(element, type, fn){
            if(element.addEventListener){
                element.addEventListener(type,fn, false);
            }else if(element.attachEvent){
                // attachEvent传入类型时,需要在前面加 "on"
                element.attachEvent("on" + type, fn);
            }else{
            	// 两个函数都不支持时,直接绑定
                element["on"+type] = fn;
            }
        }

        addEventListener(document.getElementById("btn"), "click", function(){alert("Hi!");});
    </script>
</body>
2、元素解绑事件

   用什么方式绑定事件,就应该用对应的方式解绑事件。

(1)GlobalEventHandlers.eventType
	element.onclick = null;

示例代码:
   简单的点击按钮弹框事件绑定,与点击按钮解除绑定事件。

<body>
    <input type="button" value="btn1" id="btn1">
    <input type="button" value="Unbind event" id="btn2">

    <script>
        document.getElementById("btn1").onclick = function(){
            alert("Hi!");
        }

        document.getElementById("btn2").onclick = function(){
            document.getElementById("btn1").onclick = null;
        }
    </script>
</body>
(2)EventTarget.removeEventListener()
	target.removeEventListener(type, listener[, options]);
	target.removeEventListener(type, listener[, useCapture]);
  • type:一个字符串,表示需要移除的事件类型,如 “click”;
  • listener:需要从目标事件移除的 EventListener 函数;
  • options:可选,一个指定事件侦听器特征的可选对象;
  • useCapture:可选,指定需要移除的 EventListener 函数是否为捕获监听器。如果无此参数,默认值为 false。

示例代码:
   注意,使用这种方式解绑的话,绑定时不宜使用匿名函数。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <input type="button" value="btn1" id="btn1">
    <input type="button" value="Unbind event" id="btn2">

    <script>
        function f1(){
            alert("Hi!");
        }

        document.getElementById("btn1").addEventListener("click", f1, false);
        document.getElementById("btn2").onclick = function(){
            document.getElementById("btn1").removeEventListener("click", f1);
        }
    </script>
</body>
</html>
(3)解绑事件的兼容代码

   封装事件解绑函数,兼容不同的浏览器(有些浏览器不支持removeEventListener(),而使用的是detachEvent(),比如IE8)。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <input type="button" value="btn1" id="btn1">
    <input type="button" value="Unbind event" id="btn2">


    <script>
        function addEventListener(element, type, fn){
            if(element.addEventListener){
                element.addEventListener(type,fn, false);
            }else if(element.attachEvent){
                // attachEvent传入类型时,需要在前面加 "on"
                element.attachEvent("on" + type, fn);
            }else{
                element["on"+type] = fn;
            }
        }

        function removeEventListener(element, type, fn){
            if(element.removeEventListener){
                element.removeEventListener(type,fn, false);
            }else if(element.detachEvent){
                // detachEvent传入类型时,需要在前面加 "on"
                element.detachEvent("on" + type, fn);
            }else{
                element["on"+type] = null;
            }
        }

        function f(){alert("Hi!")}

        addEventListener(document.getElementById("btn1"), "click", f);
        document.getElementById("btn2").onclick = function(){
            removeEventListener(document.getElementById("btn1"), "click", f)
        }
    </script>
</body>
</html>
3、事件的三个阶段
(1)三个阶段介绍

   当一个DOM事件被触发时,不只是在本身对象触发一次,而是会经历三个不同的阶段。

  • 捕获阶段:由外到内进行事件传播,事件从根节点流向目标节点,途中流经各个DOM节点,在各个节点上触发捕获事件,直到达到目标节点;
  • 目标(target)阶段:在此阶段中,事件传导到目标节点;
  • 事件冒泡: 由内到外进行事件传播,从目标事件位置往文档的根节点方向回溯。
(2)Event.eventPhase

   表示事件流当前处于哪一个阶段,返回一个代表当前执行阶段的整数值。

	var phase = event.eventPhase;
  • Event.NONE(0,事件未处理);
  • Event.CAPTURING_PHASE(1,事件捕获);
  • Event.AT_TARGET(2,目标阶段);
  • Event.BUBBLING_PHASE(3,冒泡阶段)。
(3)事件阶段控制

   在addEventListener()函数中,传入的第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。

4、阻止事件冒泡

   在事件冒泡阶段,会由内到外进行事件传播,直到根节点。也就是说,在多个嵌套的元素都注册了相同的事件时,如果里面元素的事件触发了,那么外层的相同事件也会随之触发。

(1)阻止事件冒泡的方式
  • event.stopPropagation()
	event.stopPropagation(); 

   阻止捕获和冒泡阶段中当前事件的进一步传播。

  • event.cancelBubble(已废弃)
	event.cancelBubble = true;
	// 某些浏览器在事件触发时,不会在事件处理函数中自动传入一个事件参数
	window.event.cancelBubble = true;

   获取或设置一个布尔值,表明当前事件是否要取消冒泡。

(2)阻止事件冒泡的兼容代码

   有的浏览器不支持stopPropagation()方法,还有的浏览器在事件处理函数中不传入事件处理参数。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #div1{
            width: 200px;
            height: 200px;
            background-color: green;
        }

        #div2{
            width: 100px;
            height: 100px;
            background-color: yellow;
        }
    </style>
</head>
<body>
    <div id="div1">
        <div id="div2"></div>
    </div>

    <script>
        function stopPropagation(e){
            if(e.stopPropagation){
                e.stopPropagation();
            }else if(e){
                // 有事件处理参数传入,没有stopPropagation()方法
                e.cancelBubble = true;
            }else{
                // 没有事件处理参数传入
                window.event.cancelBubble = true;
            }
        }

        document.getElementById("div1").onclick = function(){console.log("div1");};
        document.getElementById("div2").onclick = function(e){
            console.log("div2");
            stopPropagation(e);
        }
    </script>
</body>
</html>
5、综合案例

   实现一个在文本输入时,带文本提示功能的搜索框。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            box-sizing: border-box;
        }
 
        body {
            margin: 0;
            padding: 0;
            background: #A3D0C3;
            font-weight: 500;
            font-family: "Microsoft YaHei","宋体","Segoe UI", "Lucida Grande", 
            Helvetica, Arial,sans-serif, FreeSans, Arimo;
        }
 
        div.search {
            padding: 30px 0;
        }
 
        form {
            position: relative;
            width: 300px;
            margin: 0 auto;
        }
 
        input, button {
            border: none;
            outline: none;
        }
 
        input {
            width: 100%;
            height: 42px;
            padding-left: 13px;
        }
 
        button {
            height: 42px;
            width: 42px;
            cursor: pointer;
            position: absolute;
        }
 
        /*搜索框*/
        .bar1 input {
            border: 2px solid #7BA7AB;
            border-radius: 5px;
            background: #F9F0DA;
            color: #9E9C9C;
        }
        .bar1 button {
            top: 0;
            right: 0;
            background: #7BA7AB;
            border-radius: 0 5px 5px 0;
        }
        .bar1 button:before {
            content: "\f002";
            font-family: FontAwesome;
            font-size: 16px;
            color: #F9F0DA;
        }
    </style>
</head>
<body>
    <div class="search bar1" id="div1">
        <form>
            <input type="text" placeholder="请输入您要搜索的内容..." id="text1">
            <button type="submit"></button>
        </form>
    </div>

    <script>
        var contents = ["Apple", "Alice", "Abc", "Bob", "Bbq"];

        // 绑定的是键盘抬起事件
        document.getElementById("text1").onkeyup = function(){
            // 每次事件开始,先把原来的div删除
            if(document.getElementById("div2")){
                document.getElementById("div1").removeChild(document.getElementById("div2"));
            }

            var value = this.value;
            // 临时数组,存储提示文字数据
            var tempArr = [];
            // 构建提示数据
            for(var i = 0; i < contents.length; i++){
                if(contents[i].indexOf(value) == 0){
                    tempArr.push(contents[i]);
                }
            }

            // 如果未匹配提示内容或输入为空,则直接返回
            if(tempArr.length == 0 || value.length == 0){
                return;
            }

            // 新建div元素
            var divObj = document.createElement("div");
            divObj.id = "div2";
            divObj.style.border = "1px solid #7BA7AB";
            divObj.style.width = "300px";
            divObj.style.margin = "0 auto";

            // 向div添加内容
            for(var i = 0; i < tempArr.length; i++){
                var pObj = document.createElement("p");
                pObj.innerText = tempArr[i];
                pObj.style.marginLeft = "10px";
                divObj.appendChild(pObj);
            }

            // 将新建的div放到网页中
            document.getElementById("div1").appendChild(divObj);
        }
    </script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值