zoukankan      html  css  js  c++  java
  • Js 事件原理与事件委托

    事件原理三阶段

    捕获(由外向内)、目标、冒泡(由内向外)

    事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。即子标签发生事件后,向父级发送该事件,一直追溯到document。如:点击一个嵌套在 body中的button,则该button的onclick事件也会传递给body、document中,触发他们的onclick里触发的函数。

    案例

        <style>
            div{
                position: absolute;
                left:0;
                right:0;
                top:0;
                bottom:0;
            }
            .div0
            {
                 200px;
                height: 200px;
                background-color: skyblue;
                margin: auto;
            }
            .div1{
                 100px;
                height: 100px;
                background-color: yellowgreen;
                margin: auto;
            }
            .div2{
                 50px;
                height: 50px;
                background-color: orange;
                margin: auto;
            }
        </style>
    </head>
    <body>
        <div class="div0">
            <div class="div1">
                <div class="div2"></div>
            </div>
        </div>
        <script>
            
            div0.addEventListener("click",clickHandler0);
            div1.addEventListener("click",clickHandler1);
            div2.addEventListener("click",clickHandler2);
    
            function clickHandler0(e){
                console.log("点击div0")
            }
    
            function clickHandler1(e){
                console.log("点击div1")
            }
    
           
        </script>
    

    三阶段原理过程:

    阻止事件冒泡

    当对子元素添加了事件侦听后,执行的时候会触发父元素相同类型的事件,此时需要阻止事件冒泡。
    早期IE是没有捕获阶段的,只有冒泡,cancelBubble为阻止冒泡。后来的stopPropagaiton,既有阻止冒泡的功能,也有阻止捕获的功能,但如果译为阻止传播,那么跟cancel就是两个东西了,所以还是叫做阻止冒泡。阻止事件冒泡(传播)的方法是:

    • e.stopPropagation();通用
    • e.cancelBubble=true;仅适用在IE8及以下
    <script>
    
        div0.addEventListener("click",clickHandler0,true);//开启捕获时就执行
        div1.addEventListener("click",clickHandler1);
        div2.addEventListener("click",clickHandler2,true);//开启捕获时就执行
    
        function clickHandler2(e){
            console.log("点击div2")
            // console.log(e);
            // 停止冒泡,后面的就不会冒泡了
            e.stopPropagation();
            // 仅适用在IE8及以下
            // e.cancelBubble=true;
    
        } 
    /script>
    
    
    

    div0.addEventListener(事件类型,事件回调函数,是否捕获时执行);
    事件类型 必须是字符串,可以设置为任意字符串,但是部分字符串是系统事件类型
    事件回调函数 指向一个函数,当收到事件时执行该函数,如果没有收到不执行函数,写侦听事件时不执行函数
    是否捕获时执行 默认值是false,在冒泡时执行,捕获时不执行,

    点击div2发现执行顺序发生改变

    事件委托

    事件侦听添加(注册事件)占有内存的,尽量减少事件侦听的数量,将子元素的事件委托给父元素来执行,叫做事件委托。
    当删除对象时,一定要将对象上的侦听事件移除,否则会造成内存泄露。
    应用于:在多个元素进行侦听事件中,如果这些元素有容器嵌套关系,就需要考虑阻止冒泡。
    当多个元素需要侦听事件时,可以给这些元素的父容器增加事件,达到侦听所有元素,即是事件委托效果。
    案例:点击 li ,让其子元素 ul 切换显示。

    <body>
    <ul id="skils">
    <li>H5
        <ul>
            <li>JS
                <ul>
                <li>原生</li>
                    <li>框架
                        <ul>
                            <li>VUEJs</li>
                            <li>ReactJs</li>
                            <li>AngularJs</li>
                        </ul>
                    </li>
                <li>App</li>
                <li>小程序</li>
                <li>网页开发</li>
                </ul>
            </li>
        </ul>
    </li>
    <li>JAVA</li>
    <li>PHP</li>
    <li>LINUX</li>
    <li>PYTHON</li>
    </ul>					
    <script>
            //把子元素的侦听事件全部委托给最外层的父元素,叫做事件委托
    
    	init();
    
    	function init(){
    		var skils = document.getElementById("skils");
    		//给父元素添加侦听事件
    		skils.addEventListener("click",clickHandler);
    	}
    
    	function clickHandler(e){
    		//e.target 事件的目标 真实点击到最终的目标对象
    		//阻止冒泡,到此就结束,不再冒泡
    		e.stopPropagation();
    		//判断点击目标的节点名是不是“LI” ,不是就不执行 
    		if(e.target.nodeName !== "LI") return;
    		//判断点击目标有没有子元素
    		if(e.target.firstElementChild){
    			// 设置开关,显示和隐藏ul
    			// 第一次默认是隐藏
    			if(!e.target.bool){
    				e.target.firstElementChild.style.display = "none";
    			}else{
    				e.target.firstElementChild.style.display = "block";
    			}
    			//点击完后将e.target.bool 取反,进行显示操作
    			e.target.bool = !e.target.bool;
    			}
    		}
            </script>
    </body>
    

    扩展:

    • e.currentTarget 是事件侦听事件对象(什么对象执行addEventListener函数就是谁)
    • e.target 事件的目标对象 真实点击的最终目标对象
    • e.srcElement 事件的目标对象,兼容IE
    • 事件函数中this默认等同于e.currentTarget,都是事件侦听的对象
  • 相关阅读:
    Docker 安装 MySQL
    Docker安装
    Thymeleaf语法总结
    SpringBoot总结之事务和AOP
    SpringBoot总结之Spring Data Jpa
    SpringBoot总结之属性配置
    Spring总结之SpringMvc下
    Spring总结之SpringMvc上
    Spring总结之事务
    在什么情况下使用@ResponseBody 注解?
  • 原文地址:https://www.cnblogs.com/my12-28/p/12725880.html
Copyright © 2011-2022 走看看