17.Event对象详情、事件冒泡与捕获、事件委托、节点克隆

Event对象详情
  • Event公共属性与方法
名称描述
currentTarget其事件事件处理程序当前正在处理事件的那个元素
target返回触发此事件的元素(事件的目标元素)
type被触发的事件类型
preventDefault()通知浏览器不要执行与事件相关联的默认动作.
stopPropagation()取消事件进一步捕获或者冒泡
  • 鼠标/键盘事件Event属性
名称描述
altKey返回当前事件触发时,'ALT’是否被按下
ctrlKey返回当前事件触发时,'Ctrl’是否被按下
shiftKey返回当前事件触发时,'Shift’是否被按下
button返回当前事件被触发时,鼠标那个按钮被点击
which该属性声明了被敲击的键生成的ascii码 字符码
keyCode该属性声明了被敲击的键生成的ascii码 字符码
clientX返回当事件被触发时,鼠标指针相对于浏览器可视区域的水平坐标
clientY返回当事件被触发时,鼠标指针相对于浏览器可视区域的垂直坐标
screenX返回当某个事件被触发时,鼠标指针相对于电脑屏幕的水平坐标
screenY返回当某个事件被触发时,鼠标指针相对于电脑屏幕的垂直坐标
pageX,PageY鼠标相对于文档的位置(包括滚动条的距离,即clientX+document.body.scrollLeft,IE不支持)
offsetX,offsetY返回发生事件的地点在事件源元素的坐标系统中的x坐标和y坐标

[案例] 鼠标移动改变背景颜色

「课堂练习」

实现滑块拖动功能

要求:

  1. 实现一个可拖动的<div>元素
  2. 当鼠标按下该元素时,元素可以跟随鼠标移动,
  3. 当鼠标松开,元素不在跟随鼠标移动

效果演示:
拖动元素


阻止默认行为

介绍:默认行为就是浏览器自己触发的事件。比如:a链接的跳转,表单的提交,鼠标右键菜单显示。

思考:有时,你会遇到一些情况,你希望事件不执行它的默认行为。 最常见的例子是Web表单,例如自定义注册表单。 当你填写详细信息并按提交按钮时,自然行为是将数据提交到服务器上的指定页面进行处理,并将浏览器重定向到某种“成功消息”页面,当用户没有正确提交数据时,麻烦就来了 - 作为开发人员,你希望停止提交信息给服务器,并给他们一个错误提示,告诉他们什么做错了,以及需要做些什么来修正错误。 一些浏览器支持自动的表单数据验证功能,但由于许多浏览器不支持,因此建议你不要依赖这些功能,并实现自己的验证检查。

方法

// 阻止浏览器的默认行为
event.preventDefault();

例子
首先,一个简单的HTML表单,需要你填入名(first name)和姓(last name)

<form>
  <div>
    <label for="fname">First name: </label>
    <input id="fname" type="text">
  </div>
  <div>
    <label for="lname">Last name: </label>
    <input id="lname" type="text">
  </div>
  <div>
     <input id="submit" type="submit">
  </div>
</form>
<p></p>

这里我们用一个onsubmit事件处理程序(在提交的时候,在一个表单上发起submit事件)来实现一个非常简单的检查,用于测试文本字段是否为空。 如果是,我们在事件对象上调用preventDefault()函数,这样就停止了表单提交,然后在我们表单下面的段落中显示一条错误消息,告诉用户什么是错误的:

const form = document.querySelector('form');
const fname = document.getElementById('fname');
const lname = document.getElementById('lname');
const submit = document.getElementById('submit');
const para = document.querySelector('p');

form.onsubmit = function(e) {
  if (fname.value === '' || lname.value === '') {
    e.preventDefault();
    para.textContent = '你需要把两个名字都填上!';
  }
}

「课堂练习」

实现自定义选项菜单

要求:

  1. 当鼠标在页面中点击右键时不展示默认菜单
  2. 而是在鼠标旁边展示一个自定义的dom元素菜单
  3. 当在页面中任何地方点击左键时隐藏自定义菜单

效果演示:
自定义菜单


 <style>
        *{
            margin:0px;
            padding:0px;
        }
        .menu{
            width:200px;
            position: absolute;
            list-style: none;
            display: none;
            border: 1px solid #ccc;
        }
        .menu li{
            border-bottom: 1px solid #ccc;
            text-align: center;
            font-size:20px;
            line-height: 30px;
            cursor: pointer;
        }
        .menu li:hover{
            background-color: #ddd;
        }
    </style>
    
 <ul class="menu">
        <li>自定义菜单1</li>
        <li>自定义菜单2</li>
        <li>自定义菜单3</li>
        <li>自定义菜单4</li>
        <li>自定义菜单5</li>
        <li>自定义菜单6</li>
    </ul>
    <script>
        var menu=document.querySelector(".menu")
        document.addEventListener("contextmenu",function(event){//右键点击事件
            var e=event||window.event;
                menu.style.display="block";
                menu.style.left=e.clientX+"px";//获取鼠标相对可视区域的坐标
                menu.style.top=e.clientY+"px";//获取鼠标相对可视区域的坐标
            e.preventDefault();//阻止默认行为
        });
        document.addEventListener("click",function(){//左键点击事件
            menu.style.display="none";
        });
    </script>

事件的冒泡与捕获

概念:事件冒泡和捕捉是两种机制,主要描述当在一个元素上有两个相同类型的事件处理器被激活会发生什么。当一个事件发生在具有父元素的元素上时,现代浏览器运行两个不同的阶段 - 捕获阶段和冒泡阶段。

在捕获阶段:

  • 浏览器检查元素的最外层祖先<html>,是否在捕获阶段中注册了一个onclick事件处理程序,如果是,则运行它。
  • 然后,它移动到<html>中单击元素的下一个祖先元素,并执行相同的操作,然后是单击元素再下一个祖先元素,依此类推,直到到达实际点击的元素。

在冒泡阶段,恰恰相反:

  • 浏览器检查实际点击的元素是否在冒泡阶段中注册了一个onclick事件处理程序,如果是,则运行它
  • 然后它移动到下一个直接的祖先元素,并做同样的事情,然后是下一个,等等,直到它到达<html>元素。
    冒泡与捕获

解释:在现代浏览器中,默认情况下,所有事件处理程序都在冒泡阶段进行注册。因此,在上面的图示中,当您单击<video>时,这个单击事件从 <video> 元素向外冒泡直到 <html> 元素。

冒泡的阻止事件冒泡

概念:标准事件对象Event具有可用的名为 stopPropagation() 的函数, 当在事件对象上调用该函数时,它只会让当前事件处理程序运行,但事件不会在冒泡链上进一步扩大,因此将不会有更多事件处理器被运行不会向上冒泡。

代码

video.onclick = function(e) {
  e.stopPropagation();
  
};

注意

  • 默认情况下,绝大多数事件处理程序都是在冒泡阶段注册的,这在大多数情况下更有意义。如果您真的想在捕获阶段注册一个事件,那么您可以通过使用addEventListener()注册您的处理程序,并将可选的第三个属性设置为true

  • 不是所有的事件都能冒泡,以下事件不能冒泡:blur,focus,load,unload…

  • 冒泡到最顶层的目标不同,大部分浏览器到window,IE8到document

  • //阻止冒泡兼容写法: event.stopPropagation() IE浏览器: event.cancelBubble=true;

  什么是事件的冒泡
             在一个对象上触发某类事件(如click事件),那么click事件就会想这个事件的父级传播,从里到外,直到他被处理程序处理,或者事件到达最顶层(document/window)
          冒泡的阻止
          event.stopPropagation();
          e.stopPropagation()? e.stopPropagation(): e.cancelBubble = true //判断是否有 e.stopPropagation()?这个事件
          1)
          2)

事件委托

介绍:冒泡还允许我们利用事件委托,事件委托是通过事件冒泡这种方式,利用父级元素(或祖先元素)将事件监听器设置在其父级元素上,从而让其子元素(或后代元素)都绑定事件(注册事件)而不是每个子节点单独设置事件监听器。优势在于减少使用循环 减少DOM操作(节省内存) 动态给所有子元素或后代元素绑定事件

例子:使用事件委托重写多个元素添加随机背景色功能

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Useful event target example</title>
    <style>
      div {
        background-color: red;
        height: 100px;
        width: 25%;
        float: left;
      }
    </style>
  </head>
  <body>
    <script>
      for(let i = 1; i <= 16; i++) {
        const myDiv = document.createElement('div');
        document.body.appendChild(myDiv);
      }

      function random(number) {
        return Math.floor(Math.random() * number);
      }

      function bgChange() {
        const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
        return rndCol;
      }

      const divs = document.querySelectorAll('div');

     
      // for(let i = 0; i < divs.length; i++) {
      //   divs[i].onclick = function(e) {
      //     e.target.style.backgroundColor = bgChange();
      //   }
      // }
      // 这里无需循环给每个元素绑定事件,而是使用事件委托将点击事件绑定给他们的父元素
      document.body.onclick = function(e) {
        // 通过e.target 判断是否是需要变色的元素
          if(e.target.tagName.toLowerCase()=="div") {
            e.target.style.backgroundColor = bgChange();
          }
      }

    </script>
  </body>
</html> 

「课堂练习」

生成指定行列可修改表格

要求:

  1. 页面中包含两个<input>元素用来指定将要生成表格行与列数
  2. 生成的每个表格都可以被双击,双击后表格变成可修改状态(包含一个input元素和一个确认按钮)
  3. 用户修改完表格,input元素失去光标或点击确认按钮后表格的文本内容将会被修改
  4. 使用事件委托,给<tabel>元素绑定双击利用事件的冒泡,从而无需监听绑定给每个td元素。优化性能

效果演示:
生成指定行列可修改表格


节点额克隆 cloneNode()

  • cloneNode() 方法创建节点的拷贝,并返回该副本。
  • cloneNode() 方法克隆所有属性以及它们的值。
  • 如果您需要克隆所有后代,请把 deep 参数设置 true,否则设置为 false。
  • arguments.callee 是对函数本身的引用

效果演示:
[外链图片转存中…(img-L3JWGo6j-1627559001673)]


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值