首页 > 编程语言 >JavaScript阶段易踩坑--层级覆盖--var与let使用--事件流(捕获和冒泡)

JavaScript阶段易踩坑--层级覆盖--var与let使用--事件流(捕获和冒泡)

时间:2023-09-01 19:01:58浏览次数:32  
标签:盒子 -- JavaScript son 作用域 let 冒泡 var

刚刚走完JavaScript阶段,感觉挺爽的。但在总结的时候,我发现一些在做网页中容易错的地方,还有一些比较重要的方面。为了避免其他人在这一阶段也遇到这些问题。我今天就着重说一下在JavaScript这一阶段我容易出现的问题,从而让大家在遇到相同问题的时候可以快速解决。

一.盒子覆盖问题

只要我们做网页总会发生盒子覆盖的问题。我们在下HTML样式的时候没有注意各个盒子的层级关系,导致一些上层盒子放在了下面。当我们在 js 中通过document来获取盒子进行一些操作如:点击事件。

var boy = document.querySelector('.boy');
   boy.addEventListener('click', function() {
      boy.style.background="red"
    })

我们获取到盒子后对它注册点击事件,点击后,盒子的背景颜色变成红色。但如果这个 boy 的盒子被其他盒子覆盖,我们及时获得盒子并注册点击事件也不能对它进行我们想要的操作。解决的办法就是提升这个盒子的层级,让我们的鼠标可以点击到我们注册监听的盒子。这一部分容易被大家遗忘,如果出现使用js获取某一元素但不能进行想要的操作的时候,我们可以检查一下自己的盒子的层级关系。

二.var 和 let 的正确使用

我们走JavaScript这一阶段的时候varlet的区别与联系一定要理解透彻,否则在使用的时候就容易出现一个错误。

相似点:

局部变量:在函数体内使用 var 和 let 关键字声明的变量有点类似。它们的作用域都是 局部的: 全局变量:在函数体内或则代码块外使用 var 和 let 关键字声明的变量有点类似。它们的作用域都是 全局的:

不同点:

1.在 HTML 中, 全局作用域是针对 window 对象。使用 var 关键字声明的全局作用域变量属于 window 对象:使用 let 关键字声明的全局作用域变量不属于 window 对象: 2. 在相同的作用域或块级作用域中,不能使用 let 关键字来重置 var 关键字声明的变量,var可以重置var关键紫的变量。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h2>使用 var 声明变量</h2>
    <p id="demo"></p>
    <script>
        var x = 10;
        // 这里输出 x 为 10
        {
            var x = 2;
            // 这里输出 x 为 2
        }
        // 这里输出 x 为 2
        document.getElementById("demo").innerHTML = x;
    </script>
    </body>
    </html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h2>使用 let 声明变量</h2>
    <p id="demo"></p>
    <script>
        var x = 10;
        // 这里输出 x 为 10
        {
            let x = 2;
            // 这里输出 x 为 2
        }
        // 这里输出 x 为 10
        document.getElementById("demo").innerHTML = x;
    </script>
    </body>
    </html>
  1. 在相同的作用域或块级作用域中,不能使用 let 关键字来重置 let 关键字声明的变量: 在相同的作用域或块级作用域中,不能使用 var 关键字来重置 let 关键字声明的变量: let 关键字在不同作用域,或不同块级作用域中是可以重新声明赋值的:
<h2>JavaScript let</h2>
    <p id="demo"></p>
    <script>
        var i = 5;
        for (let i = 0; i < 10; i++) { //  使用 let 关键字, 它声明的变量作用域只在循环体内,循环体外的变量不受影响。
            // 一些代码...
        }
                //这里输出的是 10;
        document.getElementById("demo").innerHTML = i;
    </script>
<h2>JavaScript let</h2>
    <p id="demo"></p>
    <script>
        var i = 5;
        for (let i = 0; i < 10; i++) { //  使用 let 关键字, 它声明的变量作用域只在循环体内,循环体外的变量不受影响。
            // 一些代码...
        }
                        //这里输出的是 10;
        document.getElementById("demo").innerHTML = i;
    </script>

三.DOM 事件流 三个阶段

1.JS 代码中只能执行捕获或则冒泡其中的一个阶段; 2.像onclick 和 attachEvent(ie) 这些事件只能得到冒泡阶段。

DOM事件流

1.事件流描述的是从页面中接受时间的顺序; 2.事件发生时会在元素节点之间按照特定的顺序传播 这个传播的过程即DOM事件流。

比如我们给一个div注册一个点击事件: 1.捕获阶段 2.当前目标阶段 3.冒泡阶段

JavaScript阶段易踩坑--层级覆盖--var与let使用--事件流(捕获和冒泡)_作用域

冒泡事件:IE最早提出的,事件开始的时候由最具体的元素进行接收,然后逐级向上传播到DOM最顶层节点的过程。 事件捕获:网景最早提出,由DOM最顶层的节点开始,然后逐级往下传播到最具体的元素接受的过程。

我们可以这样理解:我们向水里扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点(最具体元素)之后漂浮到水面上,这个过程就相当于事件冒泡。

我们可以通过代码来更深了解捕获阶段和冒泡阶段:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div class="father">
        父亲
        <div class="son">儿子</div>
    </div>
 <script>
       // 3.捕获阶段 如addEventLister 第三个参数是 true 那么则处于捕获阶段 document ->HTML->body->father->son
        var son = document.querySelector('.son');
        var father = document.querySelector('.father');

        son.addEventListener('click', function() {
            alert("son");
        }, true);
        father.addEventListener('click', function() {
            alert("father");
        }, true);

        // 4.冒泡阶段 如addEventLister 第三个参数是 false 那么则处于冒泡阶段 son->father->body->HTML-> documentson
        var son = document.querySelector('.son');
        var father = document.querySelector('.father');

        son.addEventListener('click', function(e) {
            alert("son");
          //  e.stopPropagation();
        }, false);
        father.addEventListener('click', function(e) {
            alert("father");
        }, false);
        document.addEventListener('click', function(e) {
            alert("document");
        }, false);
    </script>
    </body>
    </html>

根据上面的代码我进行展开解释:

我们写一个father盒子,然后在father盒子里面写一个son盒子;给两个盒子都注册点击监听事件,当点击相对应的盒子的时候,弹出对应盒子的警告框。

addEventLister 第三个参数是 true 那么则处于捕获阶段,addEventLister 第三个参数是 false 那么则处于冒泡阶段。

我们先将第三个参数写成true处于捕获阶段,来看一下捕获阶段的事件流。当我们只执行捕获阶段时,我们执行代码点击son盒子。我们发现第一个出现的是father的警告框,然后才是son的警告框。这一阶段就是捕获阶段。

然后我们在将第三个参数改成false处于冒泡阶段,来看一下冒泡阶段的事件流。当我们只执行冒泡阶段,我们执行代码块点击son盒子。son盒子的警告框弹出,然后是father和document的警告框。这一阶段就是冒泡阶段。

解决冒泡的的方法:

冒泡事件常会导致一些其他的问题,如:我对网页中的某一模块进行滚轮监听,然后我的整个网页也有一个滚轮监听,当我对某一模块进行滚轮事件的之后页面也在进行滚轮事件。对网页的制作有很大的影响,这个时候我们就要想一下解决方法了。其实解决的办法很简单,该属性阻止冒泡即可。通常我们做项目话都会使用

e.stopPropagation();

来阻止某一阶段的冒泡阶段,如我上面的冒泡阶段写的阻止son的冒泡。但只是阻止了son的冒泡,如果我点击father盒子出现警示框之后document的警示框还是会出来。所以大家在使用的时候要注意。它还有一个弊端就是不适应ie6-ie8的浏览器。如果你想考虑兼容性可以加上

e.cancelBubble;

来取消冒泡。 注意: 1.实际开发中我们很少使用事件捕获,我们更加关注事件冒泡。 2.有些事件是没有冒泡的。比如:onblur, onfocus,onmouseenter,onmouseleave 3.事件冒泡有时候会带来麻烦,有时候又会很有帮助巧妙地做某些事。

这就是我走完JavaScript阶段后认为比较重要的三点。大家可以参考一下。如果有错误,希望大家之处。我们一起进步。中间有不懂得地方可以留言。我看后回应。

标签:盒子,--,JavaScript,son,作用域,let,冒泡,var
From: https://blog.51cto.com/u_16191822/7325445

相关文章

  • TX-Mini项目-指标监控服务重构-总结
    项目概述本项目的背景是,当前企业内部使用的指标监控服务的方案的成本很高,无法符合用户的需求,于是需要调研并对比测试市面上比较热门的几款开源的监控方案(选择了通用的OpenTelemetry协议:Signoz,otel-collector,jaeger;uptrace不能商用),去重构原有服务,实现降本增效:减少监控服务本身的接......
  • springboot 集成 redisson
    1.maven依赖<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.10.1</version> </dependency>2.添加配置和注入beanimportorg.redisson.Redisson;importorg.redisso......
  • 关于 Angular 应用开发里 Subject 和 BehaviorSubject 的用法一例
    笔者一直在SAP中国研究院从事CommerceCloud这款Angular应用的开发,最近工作中修复了一个bug.在SpartacusUI上点击Create按钮之后:维护User的明细数据,然后点击Save按钮:点击之后,我们期望的结果是收到一条用户成功创建的提示消息,并且页面自动导航回到点击Create......
  • mysql超出最大连接数解决方法
    遇到mysql超出最大连接数,相信不少人第一反应就是查看mysql进程,看有没有慢查询,当然这个做法是完全正确的!但是很多时候真正的问题不在这里。今天有遇到同样的问题,一味查看mysql进程和慢查询日志,无果。后来老大提点了一下,查看一下nginx日志,发现有一两个访问执行时候比较长,然后使用top......
  • Maximum Diameter 题解
    MaximumDiameter题目大意定义长度为\(n\)的序列\(a\)的权值为:所有的\(n\)个点的第\(i\)个点的度数为\(a_i\)的树的直径最大值,如果不存在这样的树,其权值为\(0\)。给定\(n\),求所有长度为\(n\)的序列的权值和。思路分析\(n\)个点的树的边数为\(n-1\),总度数......
  • JavaScript中exec()方法详解
    一、RegExp对象的声明及exec()方法的使用声明一个RegExp有两种方式:1)varre=newRegExp(pattern,modifiers);2)varre=/pattern/modifiers;注释:pattern(模式):描述了表达式的模式modifiers(修饰符)用于指定全局匹配、区分大小写的匹配和多行匹配,具体有i、g和m三类,这三类也......
  • 实用的文件编辑工具:UltraISO软碟通
    UltraISO软碟通是一个类似于WinISO的ISO文件编辑工具,UltraISO软碟通操作简单,界面简洁,用户可以用来制作启动光盘映像。不仅如此,UltraISO软碟通还可以用来处理ISO文件的启动信息,随心所欲烧录光碟。UltraISO软碟通软件简介UltraISO软碟通是一款功能强大而又方便实用的软碟文件制作/编......
  • jiangly算法模板收集
    目录数据结构树状数组并查集线段树其一其二其三懒标记线段树取模类(新版)取模类(旧版)树链剖分Splay其他二叉树其一其二分数四则运算数论欧拉筛组合数多项式相关几何图论(有向图)强连通分量缩点(无向图)求解割边、割边缩点一般图最大匹配(带花树算法)【久远】最大流费用流2-Sat【久远】字符......
  • 学习笔记:在VirtualBox上安装最新版本的Ubuntu
    学习笔记:在VirtualBox上安装最新版本的Ubuntu1.安装Ubuntu虚拟机首先,我决定在我的笔记本电脑上安装Linux操作系统,以便更深入地了解Linux和学习一些Linux命令。我选择了在VirtualBox虚拟机中安装最新版本的Ubuntu。以下是我学习和执行这一任务的步骤:1.1下载并安装VirtualBox......
  • COMP123 2D图形算法难点讨论
    COMP123Primitive2DDrawingAssignmentSpecificationInthisassignment,youwillberequiredtoimplementsomeofthealgorithmsthatwehavediscussedinlectures.Youwillneedtowriteagenericframebufferclassthatisabletorepresentimagesandd......