js-事件基础

@


① 事件概述

事件是可以被 JavaScript 侦测到的行为(触发--- 响应机制)。

网页中的每个元素都可以产生某些可以触发 JavaScript 的事件, 例如, 我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作。




② 事件三要素

1. 事件源#

触发事件的节点对象


2. 事件类型#

常见鼠标事件#

鼠标事件 触发条件
onclick 鼠标点击左键触发
ondblclick 鼠标双击触发
onmouseover 鼠标经过触发
onmouseout 鼠标离开触发
onmouseenter 鼠标经过触发
onmouseleave 鼠标离开触发
onfocus 获得鼠标焦点触发
onblur 失去鼠标焦点触发
onmousemove 鼠标移动触发
onmouseup 鼠标弹起触发
onmousedown 鼠标按下触发
contextmenu 鼠标右键菜单触发
selectstart 鼠标开始选中时触发

contextmenu#

contextmenu主要控制应该何时显示上下文菜单,主要用于开发者取消默认的上下文菜单

document.addEventListener('contextmenu', function(e) {
	e.preventDefault();//禁止事件默认行为
})

selectstart#

主要用于禁止鼠标选中( selectstart 开始选中)

document.addEventListener('selectstart', function(e) {
	e.preventDefault();//禁止事件默认行为
})

两种鼠标经过离开事件的区别#

//eg
 var father = document.querySelector('.father');
 var son = document.querySelector('.son');

 father.addEventListener('mouseover', function() {
      console.log('over');
 })
father.addEventListener('mouseout',function(){
    console.log('out');
})

 father.addEventListener('mouseenter', function() {
      console.log('enter');
 })
father.addEventListener('mouseleave',function(){
    console.log('leave');
})
  • onmouseover \ onmouseout

    它们都会冒泡,当子节点触发事件时,事件流流到父节点并执行父节点绑定的监听器。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TBMtMFvL-1630226220918)(WebAPIs.assets/a.gif)]

  • onmouseenter \ onmouseleave

    它们不会冒泡,子节点触发事件不会执行父节点的监听器

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JvKqbJM8-1630226220923)(WebAPIs.assets/b.gif)]

移动端click事件的延时问题#

移动端 click 事件会有 300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom) 页面。

解决方案:

  1. 禁用缩放。 浏览器禁用默认的双击缩放行为并且去掉 300ms 的点击延迟。

    <meta name="viewport" content="user-scalable=no">
    
  2. 利用touch事件自己封装这个事件解决 300ms 延迟。

    原理:

    • 当我们手指触摸屏幕,记录当前触摸时间
    • 当我们手指离开屏幕, 用离开的时间减去触摸的时间
    • 如果时间小于150ms,并且没有滑动过屏幕, 那么我们就定义为点击
    //封装tap,解决click 300ms 延时
    function tap (obj, callback) {
    	var isMove = false;
    	var startTime = 0; // 记录触摸时候的时间变量
    	obj.addEventListener('touchstart', function (e) {
    		startTime = Date.now(); // 记录触摸时间
    	});
    	obj.addEventListener('touchmove', function (e) {
    	isMove = true; // 看看是否有滑动,有滑动算拖拽,不算点击
    	});
    	obj.addEventListener('touchend', function (e) {
    		if (!isMove && (Date.now() - startTime) < 150) { // 如果手指触摸和离开时间小于150ms 算点击
    		callback && callback(); // 执行回调函数
    		}
    		isMove = false; // 取反 重置
    		startTime = 0;
    	});
    }
    //调用
    tap(div, function(){ // 执行代码 });
    
  3. fastclick 插件解决 300ms 延迟。 使用延时

    GitHub官网地址

    使用步骤:

    • 引入js文件

    • 在相关js文件中引入如下语句

      if ('addEventListener' in document) {
      	document.addEventListener('DOMContentLoaded', function() {
      		FastClick.attach(document.body);
      	}, false);
      }
      
      //此时,click事件就不会有延时问题
      element.addEventListener('click', function() {
                  alert(11);
      })
      

ondblclick双击事件默认选中问题#

比如双击一个元素节点(事件源)里的文本时,会默认把文本选中

解决方案:在监听函数里写上如下代码即可解决文本默认选中的特性

window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

常见的键盘事件#

键盘事件 触发条件
onkeyup 某个键盘被松开时触发
onkeydown 某个键盘被按下时触发
onkeypress 某个键盘按键被按下时并弹起时触发

注意:

  • onkeypress 和前面2个的区别是,它不识别功能键,比如左右箭头, shift 等。

滚动事件onscroll#

滚动条在滚动时会触发 onscroll 事件。


触屏事件#

触屏事件概述#

移动端浏览器兼容性较好,我们不需要考虑以前 JS 的兼容性问题,可以放心的使用原生 JS 书写效果,但是移动端也有自己独特的地方。比如触屏事件 touch(也称触摸事件),Android和 IOS 都有。

touch 对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控笔)对屏幕或者触控板操作。

常见触屏事件#

触屏touch事件 说明
touchstart 一个DOM元素上出现触点时触发
touchmove 触点在一个DOM元素上滑动时触发
touchend 触点在一个DOM元素上移开时触发

touchmove 触点移动事件默认也会触发页面滚动事件,若页面宽高超出屏幕,随着触点的移动页面也会移动


过度事件#

transitionend#

transitionend - Web API 接口参考 | MDN (mozilla.org)


change事件#

change - Web API 接口参考 | MDN (mozilla.org)


表单事件#

form.submit#

MDN

oninput#

GlobalEventHandlers.oninput - Web API 接口参考 | MDN (mozilla.org)


3. 监听器(事件处理程序 )#

事件触发后要执行的代码(函数形式),事件处理函数

<body>
    <button id="btn">唐伯虎</button>
    <script>
        // 点击一个按钮,弹出对话框
        // 1. 事件是有三部分组成  事件源  事件类型  事件处理程序   我们也称为事件三要素
        //(1) 事件源 事件被触发的对象   谁  按钮
        var btn = document.getElementById('btn');
        //(2) 事件类型  如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下
        //(3) 事件处理程序  通过一个函数赋值的方式 完成
        btn.onclick = function() {
            alert('点秋香');
        }
    </script>
</body>



③ 执行事件的步骤

  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 添加事件处理程序(采取函数赋值形式)
<!-- 案例:点击按钮弹出警示框 -->
<html>
	<button id="btn"> hello </button>
</html>
<script>
 	//1
    var btn = document.getElementById('btn');
    //2
    //btn.onclick;
    //3
    btn.onclick = function() {
        alert('world');
    }
</script>


④ 注册事件(绑定事件)

给元素添加事件,称为注册事件或者绑定事件。

1. 传统注册方式#

<button onclick=" alert('hi~')"></button>
btn.onclick = function() {
    //...
}

同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数,这是传统注册事件的唯一性

兼容性较好


2. 方法监听注册方式#

addEventListener()#

  • 语法
eventTarget.addEventListener(type, listener, useCapture)
  • 作用:该方法将指定的监听器注册到 eventTarget( 目标对象)上,当该对象触发指定的事件时, 就会执行事件处理函数。

  • 参数 说明
    type 事件类型字符串, 比如 click 、 mouseover , 注意这里不要带 on
    listener 事件处理函数, 事件发生时,会调用该监听函数
    useCapture 可选参数, 是一个布尔值,默认是 false;表示事件流
  • 特点

    • 同一个元素同一个事件可以注册多个监听器(事件处理函数)按注册顺序依次执行。
    • IE9 之前的 IE 不支持此方法

attachEvent ()#

  • 语法

    eventTarget.attachEvent(eventNameWithOn, callback)
    
  • 作用:该方法方法将指定的监听器注册到 eventTarget(目标对象) 上,当该对象触发指定的事件时, 指定的回调函数就会被执行。

  • 参数 说明
    eventNameWithOn 事件类型字符串,比如 onclick 、 onmouseover ,这里要带 on
    callback 事件处理函数,当目标触发事件时回调函数被调用
  • 特点

    • 同一个元素同一个事件可以注册多个监听器按注册顺序依次执行。
    • IE8 及早期版本支持

3.) 注册事件兼容性解决方案#

兼容性处理的原则: 首先照顾大多数浏览器,再处理特殊浏览器

/*
参数说明
element:元素对象
eventName:事件类型
fn:监听器
*/
function addEventListener(element, eventName, fn) {
	// 判断当前浏览器是否支持 addEventListener 方法,若不支持返回 undefined
	if (element.addEventListener) {
		element.addEventListener(eventName, fn); // 第三个参数 默认是false
	} else if (element.attachEvent) {
		element.attachEvent('on' + eventName, fn);
	} else {
		// 相当于 element.onclick = fn;
		element['on' + eventName] = fn;
	}
}    


⑤ 删除事件(解绑事件)

1. 传统注册方式解绑#

//eventTarget:绑定事件的元素对象
eventTarget.onclick = null;

2. 方法监听注册方式解绑#

//解除addEventListener绑定的事件
eventTarget.removeEventListener(type, listener, useCapture);
//解除attachEvent绑定的事件
eventTarget.detachEvent(eventNameWithOn, callback);

3. 删除事件兼容性解决方案#

function removeEventListener(element, eventName, fn) {
// 判断当前浏览器是否支持 removeEventListener 方法
	if (element.removeEventListener) {
		element.removeEventListener(eventName, fn); // 第三个参数 默认是false
	} else if (element.detachEvent) {
		element.detachEvent('on' + eventName, fn);
	} else {
		element['on' + eventName] = null;
	}
}	


⑥ DOM事件流

事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播, 这个传播过程即 DOM 事件流。

DOM 事件流分为3个阶段:

  1. 捕获阶段
  2. 当前目标阶段
  3. 冒泡阶段

比如:我们给页面中的一个div注册了单击事件,当你单击了div时,也就单击了body,单击了html,单击了document。

请添加图片描述

  • 事件冒泡: IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程。
  • 事件捕获: 网景最早提出, 由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。

注意

  1. JS 代码中事件的注册只能在捕获或者冒泡其中的一个阶段,但浏览器全过程事件流依然执行。
  2. onclickattachEvent 只能得到冒泡阶段。
  3. addEventListener(type, listener, useCapture)第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
  4. 实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
  5. 有些事件是没有冒泡的,比如 onblur、 onfocus、 onmouseenter、 onmouseleave


⑦ 事件对象

1. 简介#

eventTarget.onclick = function(event) {}
eventTarget.addEventListener('click', function(event){})
// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt

event 对象代表事件的状态, 比如键盘按键的状态、鼠标的位置、鼠标按钮的状态

事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象



2. 事件对象的使用#

eventTarget.onclick = function(event) {
// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
}
eventTarget.addEventListener('click', function(event) {
// 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
})

这个 event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去。
当我们注册事件时, event 对象就会根据事件类型被系统自动创建, 并依次传递给事件监听器(事件处理函数) 。



3. 事件对象的兼容性方案#

事件对象本身的获取存在兼容问题:

  1. 标准浏览器中是浏览器给方法传递的参数, 只需要定义形参 e 就可以获取到。
  2. 在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话, 需要到 window.event 中获取查找。

解决:

e = e || window.event;  


4. 事件对象的常见属性和方法#

事件对象属性方法 说明
e.target 返回触发事件的对象(标准)
e.srcElement 返回触发事件的对象(非标准,ie6~8使用)
e.type 返回事件类型,比如 click(不带on), mouseover
e.returnValue 该属性阻止默认事件(默认行为,非标准,ie6~8使用,比如不让链接跳转)
e.preventDefault() 该方法阻止默认事件(默认行为,标准)
e.stopPropagation() 阻止冒泡(标准)
e.cancelBubble 该属性阻止冒泡(非标准,ie6~8使用)

this 、 e.currentTarget \ e.target 、e.srcElement 的区别#

  • this、e.currentTarget 是事件绑定的元素, 这个函数的调用者(绑定这个事件的元素)

    • 兼容性问题:

      this兼容性较好,推荐使用

      e.currentTarget 针对IE9之前

  • e.target 、e.srcElement 是事件触发的元素。

    • 兼容性问题:

      e.target 高版本浏览器支持

      e.srcElement 针对IE9之前

    • 解决方案

      e = e || window.event;
      var target = e.target || e.srcElement;
      

阻止默认事件#

元素对象默认事件?

阻止默认事件的三种方法

  1. e.preventDefault()

    有兼容性问题,高版本适配

  2. e.returnValue

    有兼容性问题,低版本适配

  3. return false

    没兼容性问题,但其后的语句不会执行

实例

<body>
    <a href="www.baidu.com">百度</a>
</body>
<script>
	var a = document.querySelector('a');
    a.onclick = function(e) {
        //阻止链接默认的跳转事件
        //方式一
        if(e){
           e.preventDefault();
        }else{
           e = window.event;
           e.returnValue;
        }
		//方式二
         //return false;
        
    }
</script>

阻止事件冒泡#

  • 标准写法:利用事件对象里面的 stopPropagation()方法

    e.stopPropagation()
    
  • 非标准写法: IE 6-8 利用事件对象 cancelBubble 属性

    e.cancelBubble = true;
    
  • 阻止事件冒泡的兼容性解决方案

    if(e && e.stopPropagation){
    	e.stopPropagation();
    }else{
    	window.event.cancelBubble = true;
    }
    

鼠标事件对象常见属性#

鼠标事件的类型很多,但它们的事件对象都是MouseEvent

常见属性

属性 说明
e.clientX 返回鼠标相对于浏览器窗口可视区域的 X 坐标
e.clientY 返回鼠标相对于浏览器窗口可视区域的 Y 坐标
e.pageX 返回鼠标相对于文档页面的 X 坐标 IE9+支持
e.pageY 返回鼠标相对于文档页面的 Y 坐标 IE9+支持
e.screenX 返回鼠标相对于电脑屏幕的 X 坐标
e.screenY 返回鼠标相对于电脑屏幕的 Y 坐标

键盘事件对象常见属性#

键盘事件对象 说明
e.keyCode 返回改键的ASCII值
e.key 返回按下的键名
  • key有严重的兼容性问题,不推荐使用
  • keyup 、keydown 事件不区分字母大小写 a 和 A 得到的keyCode值都是65,keypress 事件 区分字母大小写 a 97 和 A 得到的是65

触摸事件对象#

TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件对象。这类事件对象用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少,等等。

类型 何时触发
touchstart 触摸元素时触发
touchmove 移动触点时触发
touchend 触点消失时触发

每个触摸事件都会各自有事件对象。

element.addEventListener('touchstart',function() {
    console.log(e);
})

请添加图片描述

常见的触摸事件对象属性:

属性 说明
e.touches 正在触摸屏幕的所有触点的一个列表
e.targetTouches 正在触摸当前DOM元素上的触点的一个列表
e.changedTouches 触点状态发生了改变的列表,从无到有,从有到无变化
e.preventDefault() 该方法阻止默认事件,比如:手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动

这三属性都返回一个TouchList对向,记录触点和触点的数量

请添加图片描述

一般都是给元素注册触摸事件,所以重点记住 targetTocuhes

targetTouches['0']//返回第一个触点对象Touch

请添加图片描述

案例:

  var div = document.querySelector('div');
        div.addEventListener('touchstart', function(e) {
            console.log(e.touches);
            console.log(e.targetTouches);
            console.log(e.changedTouches);
        })

        div.addEventListener('touchmove', function(e) {
            console.log(e.touches);
            console.log(e.targetTouches);
            console.log(e.changedTouches);
        })

        div.addEventListener('touchend', function(e) {
            console.log(e.touches);
            console.log(e.targetTouches);
            console.log(e.changedTouches);
        })

上述事件分别以一触点触发一次,输出如下结果

请添加图片描述



5. 事件委托(代理,委派)#

<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
            alert('hello');
            var list = ul.children;
            for (var i = 0; i < list.length; i++) {
                list[i].style.backgroundColor = '';
            }
            e.target.style.backgroundColor = 'pink';
        })
    </script>
</body>

事件委托也称为事件代理, 在 jQuery 里面称为事件委派。

原理不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点

作用:只操作了一次 DOM ,提高了程序的性能


作者:Hong•Guo

出处:https://www.cnblogs.com/ghnb1/p/15846679.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Hong•Guo  阅读(59)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示