zoukankan      html  css  js  c++  java
  • 从零开始学 Web 之 DOM(七)事件冒泡

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新......
    +------------------------------------------------------------
    github:https://github.com/Daotin/Web
    微信公众号:Web前端之巅
    博客园:http://www.cnblogs.com/lvonve/
    CSDN:https://blog.csdn.net/lvonve/
    +-----------------------------------------------------------
    在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享一些好玩的项目。现在就让我们一起进入 Web 前端学习的冒险之旅吧!

    一、事件冒泡

    1、什么是事件冒泡?

    事件冒泡:当有多个元素嵌套,并且这些元素绑定了相同的事件,这时候如果里面的元素事件触发了,那么外面的事件会自动触发。

    示例:

    <body>
        <div id="dv1">
            <div id="dv2">
                <div id="dv3"></div>
            </div>
        </div>
    
        <script src="common.js"></script>
        <script>
            my$("dv1").onclick = function() {
                console.log(this.id);
            }
            my$("dv2").onclick = function() {
                console.log(this.id);
            }
            my$("dv3").onclick = function() {
                console.log(this.id);
            }
        </script>
    </body>
    

    2、阻止事件冒泡

    2.1、方式一

    window.event.cancelBubble = true;

    注意: Chrome,IE8 支持,firefox 不支持

    2.2、方式二

    在事件处理函数中传一个参数 e,然后调用 e.stopPropagation();

    注意:Chrome,firefox 支持, IE8 不支持。

    window.event 和 e 都是事件处理参数对象,一个是 IE 标准,一个是 firefox 标准。

    <body>
        <div id="dv1">
            <div id="dv2">
                <div id="dv3"></div>
            </div>
        </div>
    
        <script src="common.js"></script>
        <script>
            my$("dv1").onclick = function() {
                console.log(this.id);
            }
            my$("dv2").onclick = function() {
                console.log(this.id);
                window.event.cancelBubble = true;
            }
            my$("dv3").onclick = function(e) {
                console.log(this.id);
                e.stopPropagation();
            }
        </script>
    </body>
    

    这时候可以写兼容代码的,由于用到 window ,但是没学到 BOM,所以先不写。

    3、事件的三个阶段

    1. 事件捕获阶段(从外向内) ===> 阶段 1
    2. 事件目标阶段(最开始触发事件的目标)===> 阶段 2
    3. 事件冒泡阶段(从里向外) ===> 阶段 3
    • 通过事件处理参数对象 e.eventPhase 属性可以查看当前事件所处的阶段。

      若为1:捕获阶段

      若为2:目标阶段

      若为3:冒泡阶段

    • addEventListener 绑定事件处理方法中第三个参数:控制事件的阶段

      true: 控制事件为捕获阶段

      false: 控制事件为冒泡阶段

    • 一般默认使用冒泡阶段,很少使用捕获阶段。

    <body>
        <div id="dv1">
            <div id="dv2">
                <div id="dv3"></div>
            </div>
        </div>
    
        <script src="common.js"></script>
        <script>
            my$("dv1").addEventListener("click", function(e) {
                console.log(this.id +" --- "+ e.eventPhase);
            }, false);
            my$("dv2").addEventListener("click", function(e) {
                console.log(this.id +" --- "+ e.eventPhase);
            }, false);
            my$("dv3").addEventListener("click", function(e) {
                console.log(this.id +" --- "+ e.eventPhase);
            }, false);
          
    // -------------------------------------------------------
    // addEventListener 的第三个参数为 false
    // 点击最里面的 dv3
    //dv3 --- 2 : 因为是冒泡阶段,从里向外,从 dv3开始,dv3是目标,所以为2
    //dv2 --- 3:冒泡阶段,所以为3
    //dv1 --- 3:冒泡阶段,所以为3
    
    // 如果将 false 都改为 true 的话:
    // 点击最里面的 dv3
    //dv1 --- 1:捕获阶段,从外向里,从dv1开始捕获,所以dv1为1
    //dv2 --- 1:捕获阶段,从外向里
    //dv3 --- 2:捕获阶段,从外向里,到达dv3目标,随意dv3为目标阶段。
    
        </script>
    </body>
    
    

    二、小案例

    目的:为同一个元素绑定多个不同的事件指向相同的事件处理函数。

    <body>
        <input type="button" value="按钮" id="btn" >
    
        <script src="common.js"></script>
        <script>
            my$("btn").onclick = func;
            my$("btn").onmouseover = func;
            my$("btn").onmouseout = func;
            
            function func(e) {
                switch(e.type) {
                    case "click" :
                        console.log("onclick");
                        break;
                    case "mouseover" :
                        console.log("onmouseover");
                        break;
                    case "mouseout" :
                        console.log("onmouseout");
                        break;
                    default:
                        break;
                }
            }
        </script>
    </body>
    

    使用事件处理参数对象的 type 属性可以判断事件触发时候,事件的类型,从而做出相应的事件处理。

    三、百度搜索小项目

    目标:在搜索框输入关键字,自动在搜索框下方显示相关内容。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
    
            #dv1 {
                 500px;
                margin-top: 100px;
                margin-left: 200px;
                font: 400 18px/30px "Microsoft Yahei";
                color: #595959;
            }
    
            input {
                 500px;
                height: 30px;
            }
    
            .dvv {
                 500px;
                /*height: 10px;*/
                border: 1px solid green;
            }
    
            .ps {
                padding: 2px 0 2px 5px;
                cursor: pointer;
            }
        </style>
    </head>
    <body>
    <div id="dv1">
        <input type="text" placeholder="日向雏田" id="txt">
    </div>
    
    <script src="common.js"></script>
    <script>
        var KeyWords = [
            "旋涡鸣人", "旋涡辛久奈", "旋风小子", "旋风少女",
            "日向雏田", "日向花火", "日向本家",
            "奈良鹿丸", "奈良大佐",
            "旗木卡卡西"
        ];
    
        my$("txt").onkeyup = function () {
            while(my$("dv2")) {
                my$("dv1").removeChild(my$("dv2"));
            }
            // console.log(this.value);
            var findArr = []; // 每次输入文字的时候都先清除临时数组
            for (var i = 0; i < KeyWords.length; i++) {
                if (KeyWords[i].indexOf(this.value) === 0) {
                    // console.log("yes");
                    findArr.push(KeyWords[i]);
                }
            }
            // 文本框输入了内容,并且临时数组不为空
            if ((findArr.length !== 0) && (this.value.length !== 0)) {
    
                var dvObj = document.createElement("div");
                dvObj.className = "dvv";
                dvObj.id = "dv2";
                my$("dv1").appendChild(dvObj);
    
                for (var i = 0; i < findArr.length; i++) {
                    var pObj = document.createElement("p");
                    pObj.className = "ps";
                    setInnerText(pObj, findArr[i]);
                    my$("dv2").appendChild(pObj);
    
                    pObj.onmouseover = f1; // 循环里面不要使用匿名函数
                    pObj.onmouseout = f2;
    
                }
            }
        };
    
        function f1() {
            this.style.backgroundColor = "greenyellow";
        }
        function f2() {
            this.style.backgroundColor = "";
        }
    </script>
    </body>
    </html>
    

    1、这里的候选数据本来应该来自服务器,这里用数组来模拟。
    2、这里使用的是鼠标输入文字后的鼠标抬起事件:onkeyup。
    3、 需要准备个临时数组存储于文本框输入文字匹配的字符串。
    4、当搜索框的文本为空或者临时数组的内容为空时,循环删除下拉列表。
    5、之所以输入多个文字,但是只创建了一个下拉列表的原因是因为在输入第二个文字的时候,先输入的其实是字母,这个时候不匹配,而我们在每次鼠标抬起的时候会清空临时数组,所以这个时候会先删除下拉列表,当我们输入第二个文字的时候,再重新创建相匹配的下拉列表。
    6、每次进入鼠标抬起按键时,如果有下拉列表就循环删除。
    7、注意在循环里面不要使用匿名函数。

  • 相关阅读:
    IntelliJ IDEA常用的快捷键积累总结
    Linux命令(六)之防火墙iptables的相关操作以及端口的开放
    Linux命令(五)之service服务查找、启动/停止等相关操作
    Linux命令(四)之常用文件拷贝/移动,文件解压缩,文件查找等相关的操作
    Linux命令(三)vim编辑器的常用命令
    Linux命令(一)之目录结构、Linux终端操作、关机重启等一些基本操作
    zookeeper核心知识与投票机制详解
    zuul开发实战(限流,超时解决)
    IO多路复用技术详解
    Linux五大网络IO模型图解
  • 原文地址:https://www.cnblogs.com/lvonve/p/9217677.html
Copyright © 2011-2022 走看看