10

10,第1张

文章目录 1.认识事件处理1.1 认识事件1.2 常见的事件列表 2.事件冒泡捕获2.1 认识事件流2.2 事件冒泡和事件捕获2.3 事件捕获和冒泡的过程 3.事件对象3.1 事件对象介绍3.2 event的属性解析3.3 event的方法解析3.4 事件处理函数中this 4.EventTarget类5.事件委托6.常见的事件6.1 常见鼠标事件6.2 常见键盘事件6.3 常见表单事件6.4 文档加载事件 7.window定时器方法7.1 定时器简介7.2 setTimeout的使用7.3 setInterval的使用7.3 setInterval的使用

1.认识事件处理 1.1 认识事件

Web页面需要经常和用户之间进行交互,而交互的过程中我们可能想要捕捉这个交互的过程:

比如用户点击了某个按钮、用户在输入框里面输入了某个文本、用户鼠标经过了某个位置;浏览器需要搭建一条JavaScript代码和事件之间的桥梁;当某个事件发生时,让JavaScript可以响应, 执行某个函数,所以我们需要针对事件编写处理程序(handler);

如何进行事件监听呢?

事件监听方式一:直接在HTML中编写JavaScript代码监听(很少使用);

<button onclick="console.log('按钮发生了点击')">按钮</button>

事件监听方式二:DOM属性,通过元素的on来监听事件;

<button>按钮</button>
<script>
  var btnEl = document.querySelector("button");
  btnEl.onclick = function () {
    console.log("按钮发生了点击");
  };
</script>

缺点: 无法对同一个事件绑定多个函数

事件监听方式三:通过EventTarget中的addEventListener来监听;

<button>按钮</button>
<script>
  var btnEl = document.querySelector("button");
  btnEl.addEventListener("click", function () {
    console.log("按钮事件监听的第一个函数");
  });
  btnEl.addEventListener("click", function () {
    console.log("按钮事件监听的第二个函数");
  });
  btnEl.addEventListener("click", function () {
    console.log("按钮事件监听的第三个函数");
  });
</script>

addEventListener的方式可以同时绑定多个函数

1.2 常见的事件列表 鼠标事件: click: 当鼠标点击一个元素时(触摸屏设备会在点击时生成)。mouseover / mouseout: 当鼠标指针移入/离开一个元素时。mousedown / mouseup: 当在元素上按下/释放鼠标按钮时。mousemove: 当鼠标移动时。 键盘事件: keydown 和 keyup: 当按下和松开一个按键时。 表单元素事件: submit: 当访问者提交了一个
时。focus: 当访问者聚焦于一个元素时,例如聚焦于一个 。 Document 事件: DOMContentLoaded: 当 HTML 的加载和处理均完成,DOM 被完全构建完成时。 CSS 事件: transitionend: 当一个 CSS 动画完成时。 2.事件冒泡捕获 2.1 认识事件流

事实上对于事件有一个概念叫做事件流,为什么会产生事件流呢?

我们可以想到一个问题:当我们在浏览器上对着一个元素点击时,你点击的不仅仅是这个元素本身;这是因为我们的HTML元素是存在父子元素叠加层级的;比如一个span元素是放在div元素上的,div元素是放在body元素上的,body元素是放在html元素上的;

示例代码:

<div class="box">
  <span class="word">哈哈哈哈</span>
</div>
<script>
  var spanEl = document.querySelector(".word");
  var divEl = document.querySelector(".box");
  var bodyEl = document.body;
  spanEl.addEventListener("click", function () {
    console.log("span元素发生了点击");
  });
  divEl.addEventListener("click", function () {
    console.log("div元素发生了点击");
  });
  bodyEl.addEventListener("click", function () {
    console.log("body元素发生了点击");
  });
</script>

此时当我们点击span元素时, div和body元素的事件也会触发

触发顺序为:1.span元素发生了点击2.div元素发生了点击3.body元素发生了点击

这种事件流也被称为事件冒泡

2.2 事件冒泡和事件捕获

我们会发现默认情况下事件是从最内层的span向外依次传递的顺序,这个顺序我们称之为事件冒泡(Event Bubble);

事实上,还有另外一种监听事件流的方式就是从外层到内层(body -> span),这种称之为事件捕获(Event Capture);

为什么会产生两种不同的处理流呢?

这是因为早期浏览器开发时,不管是IE还是Netscape公司都发现了这个问题;但是他们采用了完全相反的事件流来对事件进行了传递;IE采用了事件冒泡的方式,Netscape采用了事件捕获的方式;

那么我们如何去监听事件捕获的过程呢?

示例代码:

<div class="box">
  <span class="word">哈哈哈哈</span>
</div>
<script>
  var spanEl = document.querySelector(".word");
  var divEl = document.querySelector(".box");
  var bodyEl = document.body;
  spanEl.addEventListener("click", function () {
    console.log("span元素发生了点击");
  }, true);
  divEl.addEventListener("click", function () {
    console.log("div元素发生了点击");
  }, true);
  bodyEl.addEventListener("click", function () {
    console.log("body元素发生了点击");
  }, true);
</script>

在addEventListener中传入第三个参数为true, 可以监听事件捕获

此时当我们点击span元素时, div和body元素的事件也会触发

触发顺序为:1.body元素发生了点击2.div元素发生了点击3.span元素发生了点击

可以用这幅图来理解事件冒泡和事件捕获

2.3 事件捕获和冒泡的过程 如果我们事件捕获和事件冒泡都监听,那么会按照如下顺序来执行: 捕获阶段(Capturing phase): 事件(从 Window)向下走近元素。 目标阶段(Target phase): 事件到达目标元素。 冒泡阶段(Bubbling phase): 事件从元素上开始冒泡。 事实上,我们可以通过event对象来获取当前的阶段: eventPhase 开发中通常会使用事件冒泡,所以事件捕获了解即可。 3.事件对象 3.1 事件对象介绍 当一个事件发生时,就会有和这个事件相关的很多信息: 比如事件的类型是什么,你点击的是哪一个元素,点击的位置是哪里等等相关的信息;那么这些信息会被封装到一个Event对象中,这个对象由浏览器创建,称之为event对象;该对象给我们提供了想要的一些属性,以及可以通过该对象进行某些 *** 作; 如何获取这个event对象呢? event对象会在传入的事件处理(event handler)函数回调时,被系统传入;我们可以在回调函数中拿到这个event对象; 3.2 event的属性解析

常见的属性:

type:事件的类型;target:事件发生的元素;currentTarget:当前处理事件的元素;eventPhase:事件所处的阶段;offsetX、offsetY:事件发生在元素内的位置;clientX、clientY:事件发生在客户端内的位置;pageX、pageY:事件发生在客户端相对于document的位置;screenX、screenY:事件发生相对于屏幕的位置;

示例代码:

<div class="box">
  <span class="btn">
  </span>
</div>  
<script>

  var divEl = document.querySelector("div")
  var btnEl = document.querySelector(".btn")

  divEl.onclick = function(event) {
    // 1.偶尔会使用
    console.log("事件类型:", event.type)
    console.log("事件阶段:", event.eventPhase)

    // 2.比较少使用
    console.log("事件元素中位置", event.offsetX, event.offsetY)
    console.log("事件客户端中位置", event.clientX, event.clientY)
    console.log("事件页面中位置", event.pageX, event.pageY)
    console.log("事件在屏幕中位置", event.screenX, event.screenY)
  }
</script>

重点区分target/currentTarget

CSS代码


<div class="box">
  <span class="btn">
  span>
div>  
<script>

  var divEl = document.querySelector("div")
  var btnEl = document.querySelector(".btn")

  divEl.onclick = function(event) {
    // 1.偶尔会使用
    console.log("事件类型:", event.type)
    console.log("事件阶段:", event.eventPhase)

    // 2.比较少使用
    console.log("事件元素中位置", event.offsetX, event.offsetY)
    console.log("事件客户端中位置", event.clientX, event.clientY)
    console.log("事件页面中位置", event.pageX, event.pageY)
    console.log("事件在屏幕中位置", event.screenX, event.screenY)

    // 3.target/currentTarget
    //此时点击span时 span是事件发生的对象 div是事件处理的对象
    console.log(event.target) //事件发生的对象 
    console.log(event.currentTarget) //事件处理的对象 ...
  }
script>

此时点击span时 span是事件发生的对象 div是事件处理的对象

3.3 event的方法解析

常见的方法:

preventDefault:取消事件的默认行为;

<a href="http://www.baidu.com">百度a>
<script>
  var aEl = document.querySelector("a");
  aEl.onclick = function (event) {
    event.preventDefault();
  };
script>

默认情况下, 上面代码中, 点击a标签会跳转到百度, 当我们使用preventDefault()方法取消默认行为后, 点击a标签就不会跳转

stopPropagation:阻止事件的进一步传递(冒泡或者捕获都可以阻止);


<div class="box">
  <span>
    <button>按钮button>
  span>
div>

<script>
  var btnEl = document.querySelector("button");
  var spanEl = document.querySelector("span");
  var divEl = document.querySelector(".box");

  // 监听捕获阶段
  divEl.addEventListener("click", function () {
    console.log("div的事件捕获监听");
  }, true);
  spanEl.addEventListener("click", function () {
    console.log("span的事件捕获监听");
  }, true);
  btnEl.addEventListener("click", function (event) {
    console.log("buttom的事件捕获监听");
    event.stopPropagation()
  }, true);
  // 监听冒泡阶段
  divEl.addEventListener("click", function () {
    console.log("");
  });
  spanEl.addEventListener("click", function () {
    console.log("span的事件冒泡监听");
  });
  btnEl.addEventListener("click", function () {
    console.log("buttom的事件冒泡监听");
  });
script>

上面代码中默认情况下的执行顺序为:

div的事件捕获监听span的事件捕获监听buttom的事件捕获监听buttom的事件冒泡监听span的事件冒泡监听div的事件冒泡监听

当我们通过stopPropagation()方法将某一个元素的事件传递阻止时, 那么执行到该元素后, 不会在继续往下捕获或者冒泡

3.4 事件处理函数中this 在函数中,我们也可以通过this来获取当前的发生元素这是因为在浏览器内部,调用event handler是绑定到当前的target上的 事件处理函数中的this指向事件的绑定对象 4.EventTarget类

我们会发现,所有的节点、元素都继承自EventTarget

事实上Window也继承自EventTarget;

那么这个EventTarget是什么呢?

EventTarget是一个DOM接口,主要用于添加、删除、派发Event事件;

EventTarget常见的方法:

addEventListener:注册某个事件类型以及事件处理函数;

removeEventListener:移除某个事件类型以及事件处理函数;

removeEventListener的注意事项:

错误做法: btn函数并没有移除, 因为这种写法, 移除方法中相当于创建了一个新函数, 并不是移除添加事件方法中的函数

<button>按钮button>
<script>
  var btnEl = document.querySelector("button");
  // 错误做法 这种做法是无法移除的
  btnEl.addEventListener("click", function () {
    console.log("btn的监听函数");
  });
  btnEl.removeEventListener("click", function () {});
script>

正确做法: 在事件绑定时, 不能传入一个匿名函数, 需要传入一个有名称的函数才可以移除

<button>按钮button>
<script>
  var btnEl = document.querySelector("button");
  var foo = function () {
    console.log("btn的监听函数");
  };
  btnEl.addEventListener("click", foo);
  btnEl.removeEventListener("click", foo);
script>

dispatchEvent:派发某个事件类型到EventTarget上;

示例代码:

// 使用一个自己的的事件
window.addEventListener("mine", function () {
  console.log("监听到我自己的事件了");
});

// 隔五秒钟后 派发一个事件类型
setTimeout(function () {
  window.dispatchEvent(new Event("mine"));
}, 5000);
5.事件委托

事件冒泡在某种情况下可以帮助我们实现强大的事件处理模式 – 事件委托模式(也是一种设计模式)

那么这个模式是怎么样的呢?

因为当子元素被点击时,父元素可以通过冒泡可以监听到子元素的点击;并且可以通过event.target获取到当前监听的元素;

案例:一个ul中存放多个li,点击某一个li会变成红色, 其他的恢复默认色

方案一:监听每一个li的点击,并且做出响应;

<ul>
  <li>1li>
  <li>2li>
  <li>3li>
  <li>4li>
  <li>5li>
ul>
<script>
  var liEl = document.querySelectorAll("li");
  // 循环为li绑定事件
  for (var i = 0; i < liEl.length; i++) {
    // 将所有按钮样式全部清除
    liEl[i].onclick = function () {
      for (var i = 0; i < liEl.length; i++) {
        liEl[i].style.color = "";
      }
      // 在为当前按钮单独设置样式
      this.style.color = "red";
    };
  }
script>

方案二:在ul中监听点击,并且通过event.target拿到对应的li进行处理;(事件委托的模式)

因为这种方案并不需要遍历后给每一个li上添加事件监听,所以它更加高效;

并解决点击ul时会添加所有样式的小bug

<ul>
  <li>1li>
  <li>2li>
  <li>3li>
  <li>4li>
  <li>5li>
ul>
<script>
  var ulEl = document.querySelector("ul");
  // 给ul添加事件
  ulEl.onclick = function (event) {
    //判断当前点击元素是否是ulEl 如果不是移除其他li的样式
    for (var i = 0; i < ulEl.children.length; i++) {
      if (event.target !== ulEl) {
        ulEl.children[i].style.color = "";
      }
    }
    // 当前点击元素不为ul时 单独为当前点击的li元素添加样式
    if (event.target !== ulEl) {
      event.target.style.color = "red";
    }
  };
script>

上面代码中采用for循环将所有的样式移除了一遍, 而有些是原本就没有样式的, 这样做性能并不高

上面代码中提高性能的方法

<ul>
  <li>1li>
  <li>2li>
  <li>3li>
  <li>4li>
  <li>5li>
ul>
<script>
  var ulEl = document.querySelector("ul");
  // 用一个变量记录哪一个元素添加了样式
  var colorEl = null;
  // 给ul添加事件
  ulEl.onclick = function (event) {
    // 将设置了样式的元素 移除样式 并且判断当前点击元素是否是ulEl 如果不是才移除
    if (colorEl && event.target !== ulEl) {
      colorEl.style.color = "";
    }
    // 为当前点击的li元素添加样式 并且判断当前点击元素是否是ulEl 如果不是才添加
    if (event.target !== ulEl) {
      event.target.style.color = "red";
    }
    // 并将添加了样式的元素保存在colorEl中
    colorEl = event.target;
  };
script>
6.常见的事件 6.1 常见鼠标事件

接下来我们来看一下常见的鼠标事件(不仅仅是鼠标设备,也包括模拟鼠标的设备,比如手机、平板电脑)

常见的鼠标事件:

属性描述
click当用户点击某个对象时调用的事件句柄。
contextmenu在用户点击鼠标右键打开上下文菜单时触发
dblclick当用户双击某个对象时调用的事件句柄。
mousedown鼠标按钮被按下。
mouseup鼠标按键被松开。
mouseover鼠标移到某元素之上。(支持冒泡)
mouseout鼠标从某元素移开。(支持冒泡)
mouseenter当鼠标指针移动到元素上时触发。(不支持冒泡)
mouseleave当鼠标指针移出元素时触发。(不支持冒泡)
mousemove鼠标被移动。

mouseover和mouseenter的区别

mouseenter和mouseleave 不支持冒泡进入子元素依然属于在该元素内,没有任何反应 mouseover和mouseout 支持冒泡进入元素的子元素时 先调用父元素的mouseout再调用子元素的mouseover因为支持冒泡,所以会将mouseover传递到父元素中; 6.2 常见键盘事件

常见的键盘事件:

属性描述
onkeydown某个键盘按键被按下。
onkeypress某个键盘按键被按下。
onkeyup某个键盘按键被松开。

键盘事件的执行顺序是: onkeydown、onkeypress、onkeyup

down当键盘按下去的那一刻, 事件发生;press在文本被输入的时候, 事件发生;up发生在文本输入完成(按键抬起);

我们可以通过event对象的key和code来区分按下的键:

code:“按键代码”(“KeyA”,“ArrowLeft” 等),特定于键盘上按键的物理位置。key:字符(“A”,“a” 等),对于非字符(non-character)的按键,通常具有与 code 相同的值。)

示例代码:

<input type="text" />
<button>搜索button>
<script>
  var inputEl = document.querySelector("input");
  var buttonEl = document.querySelector("button");
  // 点击按钮实现搜索功能
  buttonEl.onclick = function () {
    console.log("搜索", inputEl.value);
  };
  // 点击键盘Enter键 实现搜索功能
  inputEl.onkeyup = function (event) {
    if (event.key == "Enter") {
      console.log("搜索", inputEl.value);
    }
  };
  // 按下s自动获取焦点
  document.onkeyup = function (event) {
    if (event.code === "KeyS") {
      inputEl.focus();
    }
  };
script>
6.3 常见表单事件

针对表单也有常见的事件:

属性
onchange该事件在表单元素的内容改变时触发( , ,