• JavaScript:web中的简单事件处理


    首先应树立一种HTML、CSS、JavaScript三者独立的观念


    JavaScript脚本的事件处理

    不要在HTML元素中以属性的方式添加事件处理

    <button onclick="doSomething()">Press me</button>
    

    甚至是直接写入脚本代码

    <button onclick="alert('Hello, this is my old-fashioned event handler!');">Press me</button>
    

    正确的姿势

    ①JavaScript中使用事件处理器属性

    var btn = document.querySelector('button');
    
    function f() {}
    
    btn.onclick = f;
    

    甚至是批量添加事件处理

    var buttons = document.querySelectorAll('button');
    
    for (var i = 0; i < buttons.length; i++) {
      buttons[i].onclick = f;
    }
    

    addEventListener()removeEventListener()
    一看就是更为规范的监听器方法

    function f(){}
    btn.addEventListener('click', f);
    btn.addEventListener('click', f);
    

    使用此方法可为一个对象添加多个事件处理
    而使用 element.click=f; 方式添加多个事件处理时,后添加的会覆盖先前的


    事件对象

    事件对象,在事件触发时被自动传递给事件处理函数,以提供额外的功能和信息

    function f(e) {
      console.log(e);
    }  
    
    btn.addEventListener('click', f);
    

    如 e.target 始终是触发事件的对象的引用,(类似直接使用 this,同Java中的this
    大多数事件处理器的事件对象都有可用的标准属性和函数
    一些特殊的对象会添加一些专业属性提供额外的数据


    事件冒泡及捕获

    与Android中的事件分发(事件的传递)有相似之处,也就存在类似的问题

    事件冒泡和捕获是事件传递的两种方式

    在现代浏览器中,默认情况下,所有事件处理程序都在冒泡阶段进行注册,即是说,事件传播默认采用冒泡方式

    使用addEventListener()并将第三个参数置为true表示在事件传播的捕获阶段注册监听器

    冒泡

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

    捕获则相反:

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

    当一个事件发生在具有父元素的元素上时,现代浏览器会运行这两个不同的阶段

    因此,有时会出现不想发生的状况

    <button>Display video</button>
    
    <div class="hidden">
      <video>
        <source src="rabbit320.mp4" type="video/mp4">
        <source src="rabbit320.webm" type="video/webm">
        <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p>
      </video>
    </div>
    
    .hidden{visibility: hidden;}
    .showing{visibility: visible;}
    
    	var btn = document.querySelector('button');
        var videoBox = document.querySelector('div');
        var video = document.querySelector('video');
    
        btn.onclick = function() {
            videoBox.setAttribute('class','showing');
        };
    
        videoBox.onclick = function() {
            videoBox.setAttribute('class','hidden');
        };
    
        video.onclick = function() {
            video.play();
        };
    

    由上面的代码,点击button视频会出现,当我们点击video想要播放视频时,事件在经过video处理后,会被传递到div,然后div设置为隐藏,video随着div消失了

    那么怎样解决问题?

    • 使用事件的stopPropagation()方法使事件停止传播
      只需将上述js文件的video的事件处理修改为
    video.onclick = function(e) {
    		e.stooPropagation();
            video.play();
    };
    

    即可

    事件冒泡及捕获的意义

    当有多个子元素以类似的方式处理事件的时候,可以只为为它们的父级元素添加一个事件处理
    一个很好的例子是一系列列表项,如果你想让每个列表点击时弹出一条信息,您可以将click单击事件监听器设置在父元素<ul>上,它将会冒泡到列表项上

    <div>
        <span>1</span><span>2</span><span>3</span><br>
        <span>4</span><span>5</span><span>6</span><br>
        <span>7</span><span>8</span><span>9</span>
    </div>
    

    以下代码为父级元素添加事件处理,处理子元素的点击事件

    function random(number) {
            return Math.floor(Math.random()*(number+1));
        }
    
        var div = document.querySelector("div");
    
        document.querySelector("div").addEventListener("click", function (e) {
            if(!(e.target instanceof HTMLDivElement)){
                e.target.style.backgroundColor = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
            }
        });
    

    这种做法又形象地称为:事件委托


    注意JS中的执行顺序

    var div = document.querySelector("div").onclick = function(e){
    	div.setAttribute('class', 'hidden');
    };
    

    这里定义出的div实际上是后面的匿名函数,而非想要的div对象

    JS真的太灵活了
    div.onclick得到的是onclick方式注册的监听器
    div.onclick()、div.onclick(e)则是调用这个事件处理函数。。

    且div.onclick()访问不到addEventListener()注册的事件处理

    事件并不是JavaScript的核心部分——它们是在浏览器Web APIs中定义的
    JavaScript在不同环境下使用不同的事件模型


    2019/5/18

  • 相关阅读:
    前端与算法 leetcode 28.实现 strStr()
    前端与算法 leetcode 27.移除元素
    npm钉钉脚手架,支持考勤信息获取
    VSCode 使用Settings Sync同步配置(最新版教程,非常简单)
    VSCode 远程开发(带免密)
    vscode保存代码,自动按照eslint规范格式化代码设置
    matplotlib 3D数据-【老鱼学matplotlib】
    matplotlib等高线图-【老鱼学matplotlib】
    matplotlib柱状图-【老鱼学matplotlib】
    matplotlib散点数据-【老鱼学matplotlib】
  • 原文地址:https://www.cnblogs.com/kafm/p/12721811.html
Copyright © 2020-2023  润新知