当前位置: 首页 > news >正文

JS13-事件的绑定和事件对象Event

绑定事件的两种方式/DOM事件的级别

DOM0的写法:onclick

    element.onclick = function () {}

举例:

<body>
<button>点我</button>
<script>var btn = document.getElementsByTagName("button")[0];//这种事件绑定的方式,如果绑定多个,则后面的会覆盖掉前面的btn.onclick = function () {console.log("事件1");}btn.onclick = function () {console.log("事件2");}</script>
</body>

点击按钮后,上方代码的打印结果:

事件2

我们可以看到,DOM对象.事件 = 函数的这种绑定事件的方式:一个元素的一个事件只能绑定一个响应函数。如果绑定了多个响应函数,则后者会覆盖前者。

DOM2的写法:addEventListener(高版本浏览器)

    element.addEventListener('click', function () {}, false);

参数解释:

  • 参数1:事件名的字符串(注意,没有on)

  • 参数2:回调函数:当事件触发时,该函数会被执行

  • 参数3:true表示捕获阶段触发,false表示冒泡阶段触发(默认)。如果不写,则默认为false。【重要】

举例:

<body>
<button>按钮</button>
<script>var btn = document.getElementsByTagName("button")[0];// addEventListener: 事件监听器。 原事件被执行的时候,后面绑定的事件照样被执行// 这种写法不存在响应函数被覆盖的情况。(更适合团队开发)btn.addEventListener("click", fn1);btn.addEventListener("click", fn2);function fn1() {console.log("事件1");}function fn2() {console.log("事件2");}</script>
</body>

点击按钮后,上方代码的打印结果:

    事件1事件2

我们可以看到,addEventListener()这种绑定事件的方式:

  • 一个元素的一个事件,可以绑定多个响应函数。不存在响应函数被覆盖的情况。执行顺序是:事件被触发时,响应函数会按照函数的绑定顺序执行。

  • addEventListener()中的this,是绑定事件的对象。

  • addEventListener()不支持 IE8 及以下的浏览器。在IE8中可以使用attachEvent来绑定事件(详见下一小段)。

DOM2的写法:attachEvent(IE8及以下版本浏览器)

    element.attachEvent('onclick', function () {});

参数解释:

  • 参数1:事件名的字符串(注意,有on)

  • 参数2:回调函数:当事件触发时,该函数会被执行

举例:

    <body><button>按钮</button><script>var btn = document.getElementsByTagName('button')[0];btn.attachEvent('onclick', function() {console.log('事件1');});btn.attachEvent('onclick', function() {console.log('事件2');});</script></body>

在低版本的IE浏览器上,点击按钮后,上方代码的打印结果:

    事件2事件1

我们可以看到,attachEvent()这种绑定事件的方式:

  • 一个元素的一个事件,可以绑定多个响应函数。不存在响应函数被覆盖的情况。注意:执行顺序是,后绑定的先执行。

  • attachEvent()中的this,是window

兼容性写法

上面的内容里,需要强调的是:

  • addEventListener()中的this,是绑定事件的对象。

  • attachEvent()中的this,是window。

既然这两个写法的this不同,那么,有没有一种兼容性的写法可以确保这两种绑定方式的this是相同的呢?我们可以封装一下。代码如下:

    <body><button>按钮</button><script>var btn = document.getElementsByTagName('button')[0];myBind(btn , "click" , function(){alert(this);});//定义一个函数,用来为指定元素绑定响应函数/** addEventListener()中的this,是绑定事件的对象* attachEvent()中的this,是window*  需要统一两个方法this*//** 参数:*  element 要绑定事件的对象*  eventStr 事件的字符串(不要on)*  callback 回调函数*/function myBind(element , eventStr , callback){if(element.addEventListener){//大部分浏览器兼容的方式element.addEventListener(eventStr , callback , false);}else{/** this是谁,由调用方式决定* callback.call(element)*///IE8及以下element.attachEvent("on"+eventStr , function(){//在匿名函数 function 中调用回调函数callbackcallback.call(element);});}}</script></body>

事件对象

当事件的响应函数被触发时,会产生一个事件对象event。浏览器每次都会将这个事件event作为实参传进之前的响应函数。

这个对象中包含了与当前事件相关的一切信息。比如鼠标的坐标、键盘的哪个按键被按下、鼠标滚轮滚动的方向等。

获取 event 对象(兼容性问题)

所有浏览器都支持event对象,但支持的方式不同。如下。

(1)普通浏览器的写法是 event。比如:

(2)ie 678 的写法是 window.event。此时,事件对象 event 是作为window对象的属性保存的。

于是,我们可以采取一种兼容性的写法。如下:

    event = event || window.event; // 兼容性写法

代码举例:

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><title></title>
</head>
<body>
<script>//点击页面的任何部分document.onclick = function (event) {event = event || window.event; 兼容性写法console.log(event);console.log(event.timeStamp);console.log(event.bubbles);console.log(event.button);console.log(event.pageX);console.log(event.pageY);console.log(event.screenX);console.log(event.screenY);console.log(event.target);console.log(event.type);console.log(event.clientX);console.log(event.clientY);}
</script>
</body>
</html>

event 属性

event 有很多属性,比如:

由于pageX 和 pageY的兼容性不好,我们可以这样做:

  • 鼠标在页面的位置 = 滚动条滚动的距离 + 可视区域的坐标。

Event举例

举例1:使 div 跟随鼠标移动

代码实现:

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title></title><style type="text/css">#box1 {width: 100px;height: 100px;background-color: red;/** 开启box1的绝对定位*/position: absolute;}</style><script type="text/javascript">window.onload = function() {/** 使div可以跟随鼠标移动*///获取box1var box1 = document.getElementById("box1");//给整个页面绑定:鼠标移动事件document.onmousemove = function(event) {//兼容的方式获取event对象event = event || window.event;// 鼠标在页面的位置 = 滚动条滚动的距离 + 可视区域的坐标。var pagex = event.pageX || scroll().left + event.clientX;var pagey = event.pageY || scroll().top + event.clientY;//   设置div的偏移量(相对于整个页面)// 注意,如果想通过 style.left 来设置属性,一定要给 box1开启绝对定位。box1.style.left = pagex + "px";box1.style.top = pagey + "px";};};// scroll 函数封装function scroll() {return {//此函数的返回值是对象left: window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop,right:window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft};}</script></head><body style="height: 1000px;width: 2000px;"><div id="box1"></div></body>
</html>

举例2:获取鼠标距离所在盒子的距离

关键点:

    鼠标距离所在盒子的距离 = 鼠标在整个页面的位置 - 所在盒子在整个页面的位置

代码演示:

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><title></title><style>.box {width: 300px;height: 200px;padding-top: 100px;background-color: pink;margin: 100px;text-align: center;font: 18px/30px "simsun";cursor: pointer;}</style>
</head>
<body>
<div class="box"></div><script src="animate.js"></script>
<script>//需求:鼠标进入盒子之后只要移动,哪怕1像素,随时显示鼠标在盒子中的坐标。//技术点:新事件,onmousemove:在事件源上,哪怕鼠标移动1像素也会触动这个事件。//一定程度上,模拟了定时器//步骤://1.老三步和新五步//2.获取鼠标在整个页面的位置//3.获取盒子在整个页面的位置//4.用鼠标的位置减去盒子的位置赋值给盒子的内容。//1.老三步和新五步var div = document.getElementsByTagName("div")[0];div.onmousemove = function (event) {event = event || window.event;//2.获取鼠标在整个页面的位置var pagex = event.pageX || scroll().left + event.clientX;var pagey = event.pageY || scroll().top + event.clientY;//3.获取盒子在整个页面的位置// var xx =// var yy =//4.用鼠标的位置减去盒子的位置赋值给盒子的内容。var targetx = pagex - div.offsetLeft;var targety = pagey - div.offsetTop;this.innerHTML = "鼠标在盒子中的X坐标为:" + targetx + "px;<br>鼠标在盒子中的Y坐标为:" + targety + "px;"}</script>
</body>
</html>

实现效果:

举例3:商品放大镜

代码实现:

(1)index.html:

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><title></title><style>* {margin: 0;padding: 0;}.box {width: 350px;height: 350px;margin: 100px;border: 1px solid #ccc;position: relative;}.big {width: 400px;height: 400px;position: absolute;top: 0;left: 360px;border: 1px solid #ccc;overflow: hidden;display: none;}/*mask的中文是:遮罩*/.mask {width: 175px;height: 175px;background: rgba(255, 255, 0, 0.4);position: absolute;top: 0;left: 0;cursor: move;display: none;}.small {position: relative;}img {vertical-align: top;}</style><script src="tools.js"></script><script>window.onload = function () {//需求:鼠标放到小盒子上,让大盒子里面的图片和我们同步等比例移动。//技术点:οnmοuseenter==onmouseover 第一个不冒泡//技术点:οnmοuseleave==onmouseout  第一个不冒泡//步骤://1.鼠标放上去显示盒子,移开隐藏盒子。//2.老三步和新五步(黄盒子跟随移动)//3.右侧的大图片,等比例移动。//0.获取相关元素var box = document.getElementsByClassName("box")[0];var small = box.firstElementChild || box.firstChild;var big = box.children[1];var mask = small.children[1];var bigImg = big.children[0];//1.鼠标放上去显示盒子,移开隐藏盒子。(为小盒子绑定事件)small.onmouseenter = function () {//封装好方法调用:显示元素show(mask);show(big);}small.onmouseleave = function () {//封装好方法调用:隐藏元素hide(mask);hide(big);}//2.老三步和新五步(黄盒子跟随移动)//绑定的事件是onmousemove,而事件源是small(只要在小盒子上移动1像素,黄盒子也要跟随)small.onmousemove = function (event) {//新五步event = event || window.event;//想要移动黄盒子,必须要知道鼠标在small小图中的位置。var pagex = event.pageX || scroll().left + event.clientX;var pagey = event.pageY || scroll().top + event.clientY;//x:mask的left值,y:mask的top值。var x = pagex - box.offsetLeft - mask.offsetWidth / 2; //除以2,可以保证鼠标mask的中间var y = pagey - box.offsetTop - mask.offsetHeight / 2;//限制换盒子的范围//left取值为大于0,小盒子的宽-mask的宽。if (x < 0) {x = 0;}if (x > small.offsetWidth - mask.offsetWidth) {x = small.offsetWidth - mask.offsetWidth;}//top同理。if (y < 0) {y = 0;}if (y > small.offsetHeight - mask.offsetHeight) {y = small.offsetHeight - mask.offsetHeight;}//移动黄盒子console.log(small.offsetHeight);mask.style.left = x + "px";mask.style.top = y + "px";//3.右侧的大图片,等比例移动。//如何移动大图片?等比例移动。//    大图片/大盒子 = 小图片/mask盒子//    大图片走的距离/mask走的距离 = (大图片-大盒子)/(小图片-黄盒子)
//                var bili = (bigImg.offsetWidth-big.offsetWidth)/(small.offsetWidth-mask.offsetWidth);//大图片走的距离/mask盒子都的距离 = 大图片/小图片var bili = bigImg.offsetWidth / small.offsetWidth;var xx = bili * x;  //知道比例,就可以移动大图片了var yy = bili * y;bigImg.style.marginTop = -yy + "px";bigImg.style.marginLeft = -xx + "px";}}</script>
</head>
<body>
<div class="box"><div class="small"><img src="images/001.jpg" alt=""/><div class="mask"></div></div><div class="big"><img src="images/0001.jpg" alt=""/></div>
</div>
</body>
</html>

(2)tools.js:

/*** Created by smyhvae on 2018/02/03.*///显示和隐藏
function show(ele) {ele.style.display = "block";
}function hide(ele) {ele.style.display = "none";
}function scroll() {  // 开始封装自己的scrollTopif (window.pageYOffset != null) {  // ie9+ 高版本浏览器// 因为 window.pageYOffset 默认的是  0  所以这里需要判断return {left: window.pageXOffset,top: window.pageYOffset}}else if (document.compatMode === "CSS1Compat") {    // 标准浏览器   来判断有没有声明DTDreturn {left: document.documentElement.scrollLeft,top: document.documentElement.scrollTop}}return {   // 未声明 DTDleft: document.body.scrollLeft,top: document.body.scrollTop}
}

效果演示:

相关文章:

JS13-事件的绑定和事件对象Event

绑定事件的两种方式/DOM事件的级别 DOM0的写法&#xff1a;onclick element.onclick function () {}举例&#xff1a; <body> <button>点我</button> <script>var btn document.getElementsByTagName("button")[0];//这种事件绑定的方式…...

pycorrector检测OCR错字实践

参考&#xff1a;https://github.com/shibing624/pycorrector/tree/master/examples/macbert stopwords.txt 添加专业停用词&#xff0c;避免错误 设置自定义词典&#xff0c;避免将正确的词错误检测成错误的词 from pycorrector import Corrector m Corrector() m.set_cus…...

RDD算子介绍(三)

1. join 将相同的key的值连接在一起&#xff0c;值的类型可以不同 val rdd1 : RDD[(String, Int)] sc.makeRDD(List(("a", 1), ("b", 2), ("c", 3))) val rdd2 : RDD[(String, Int)] sc.makeRDD(List(("a", 4), ("b", 5…...

Redis的脑裂问题

Redis 脑裂&#xff08;Split-brain&#xff09;问题是指在分布式系统中&#xff0c;特别是基于主从复制和哨兵&#xff08;Sentinel&#xff09;模式的Redis集群中&#xff0c;由于网络分区&#xff08;network partition&#xff09;而导致部分节点组成了独立可用的服务&…...

【算法】雪花算法生成分布式 ID

SueWakeup 个人中心&#xff1a;SueWakeup 系列专栏&#xff1a;学习Java框架 个性签名&#xff1a;人生乏味啊&#xff0c;我欲令之光怪陆离 本文封面由 凯楠&#x1f4f7; 友情赞助播出! 目录 1. 什么是分布式 ID 2. 分布式 ID 基本要求 3. 数据库主键自增 4. UUID 5. S…...

FFplay使用滤镜添加字幕到现有视频显示

1.创建字幕文件4k.srt 4k.srt内容: 1 00:00:01.000 --> 00:00:30.000 日照香炉生紫烟2 00:00:31.000 --> 00:00:60.000 遥看瀑布挂前川3 00:01:01.000 --> 00:01:30.000 飞流直下三千尺4 00:01:31.000 --> 00:02:00.000 疑是银河落九天2.通过使用滤镜显示字幕在视…...

【Python + Django】Django模板语法 + 请求和响应

前言&#xff1a; 现在现在&#xff0c;我们要开始将变量的值展现在页面上面啦&#xff01; 要是只会显示静态页面&#xff0c;我们的页面也太难看和死板了&#xff0c; 并且数据库的数据也没法展现在页面上。 但是呢&#xff0c;模板语法学习之后就可以啦&#xff01;&…...

大数据面试总结 四

1、当hadoop集群中某一个节点挂了&#xff0c;内部数据流程是如何进行的&#xff1f; 每一个datanode都会定期向namenode发送heardbeat消息&#xff0c;当一段时间namenode没有接收到某一个datanode的消息&#xff0c;此时namenode就会将该datanode标记为死亡&#xff0c;并不…...

Spring Boot: 使用MongoOperations操作mongodb

一、添加依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4…...

PyTorch 深度学习(GPT 重译)(六)

十四、端到端结节分析&#xff0c;以及接下来的步骤 本章内容包括 连接分割和分类模型 为新任务微调网络 将直方图和其他指标类型添加到 TensorBoard 从过拟合到泛化 在过去的几章中&#xff0c;我们已经构建了许多对我们的项目至关重要的系统。我们开始加载数据&#xf…...

MyBatis3源码深度解析(十七)MyBatis缓存(一)一级缓存和二级缓存的实现原理

文章目录 前言第六章 MyBatis缓存6.1 MyBatis缓存实现类6.2 MyBatis一级缓存实现原理6.2.1 一级缓存在查询时的使用6.2.2 一级缓存在更新时的清空 6.3 MyBatis二级缓存的实现原理6.3.1 实现的二级缓存的Executor类型6.3.2 二级缓存在查询时使用6.3.3 二级缓存在更新时清空 前言…...

Go --- Go语言垃圾处理

概念 垃圾回收&#xff08;GC-Garbage Collection&#xff09;暂停程序业务逻辑SWT&#xff08;stop the world&#xff09;程序根节点&#xff1a;程序中被直接或间接引用的对象集合&#xff0c;能通过他们找出所有可以被访问到的对象&#xff0c;所以Go程序的根节点通常包括…...

力扣每日一题30:串联所有单词的子串

题目描述 给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如&#xff0c;如果 words ["ab","cd","ef"]&#xff0c; 那么 &q…...

vim | vim的快捷命令行

快捷进入shell界面 -> :nnoremap <F8> :sh<CR> -> 绑定到了F8 :nnoremap <F8> :sh<CR> 快捷执行 -> :nnoremap <F5> :wa<CR>:!g % -o a.out && ./a.out<CR> -> 绑定到了F5 :nnoremap <F5> :wa<CR>…...

项目管理平台-01-BugClose 入门介绍

拓展阅读 Devops-01-devops 是什么&#xff1f; Devops-02-Jpom 简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件 代码质量管理 SonarQube-01-入门介绍 项目管理平台-01-jira 入门介绍 缺陷跟踪管理系统&#xff0c;为针对缺陷管理、任务追踪和项目管理的商业…...

web集群-lvs-DR模式基本配置

目录 环境&#xff1a; 一、配置RS 1、安装常见软件 2、配置web服务 3、添加vip 4、arp抑制 二、配置LVS 1、添加vip 2、安装配置工具 3、配置DR 三、测试 四、脚本方式配置 1、LVS-DR 2、LVS-RS 环境&#xff1a; master lvs 192.168.80.161 no…...

基于深度学习的面部情绪识别算法仿真与分析

声明&#xff1a;以下内容均属于本人本科论文内容&#xff0c;禁止盗用&#xff0c;否则将追究相关责任 基于深度学习的面部情绪识别算法仿真与分析 摘要结果分析1、本次设计通过网络爬虫技术获取了七种面部情绪图片&#xff1a;吃惊、恐惧、厌恶、高兴、伤心、愤怒、自然各若…...

C语言经典面试题目(十六)

1、什么是C语言中的指针常量和指针变量&#xff1f;它们有什么区别&#xff1f; 在C语言中&#xff0c;指针常量和指针变量是指针的两种不同类型。它们的区别在于指针的指向和指针本身是否可以被修改。 指针常量&#xff1a;指针指向的内存地址不可变&#xff0c;但指针本身的…...

【C语言】文件操作揭秘:C语言中文件的顺序读写、随机读写、判断文件结束和文件缓冲区详细解析【图文详解】

欢迎来CILMY23的博客喔&#xff0c;本篇为【C语言】文件操作揭秘&#xff1a;C语言中文件的顺序读写、随机读写、判断文件结束和文件缓冲区详细解析【图文详解】&#xff0c;感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞关注收藏。 前言 欢迎来到本篇博客&…...

JAVA八股文面经问题整理第6弹

文章目录 目录 文章目录 提问问题 问题1 问题2 问题3 问题4 问题5 问题6 问题7 问题8 问题9 问题10 问题11 问题12 写在最后 提问问题 介绍一下Linux常⽤命令&#xff0c;例如&#xff1a;Vim快捷键&#xff0c;常⽤查看Log的命令&#xff0c;路径相关&#x…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]

报错信息&#xff1a;libc.so.6: cannot open shared object file: No such file or directory&#xff1a; #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...