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

posted @ 2019-05-18 16:09  kafm  阅读(103)  评论(0编辑  收藏  举报