zoukankan      html  css  js  c++  java
  • 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 Binary Tree Inorder Traversal
    LeetCode Populating Next Right Pointers in Each Node
    LeetCode Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode Reverse Linked List II
    LeetCode Populating Next Right Pointers in Each Node II
    LeetCode Pascal's Triangle
    Palindrome Construct Binary Tree from Preorder and Inorder Traversal
    Pascal's Triangle II
    LeetCode Word Ladder
    LeetCode Binary Tree Zigzag Level Order Traversal
  • 原文地址:https://www.cnblogs.com/kafm/p/12721811.html
Copyright © 2011-2022 走看看