js事件(十一)

EVENT

一、什么是事件

  • 一个事件的组成
    • 触发谁的事件: 事件源
    • 触发什么事件: 事件类型
    • 触发后做什么: 事件处理函数
js 复制代码
var oDiv = document.querySelector("div");

oDiv.onclick = function () {};
/**
 * 触发谁的事件 ---> oDiv ---> 事件源就是 oDiv
 * 触发什么事件 ---> onclick ---> 事件类型就是 click
 * 触发后做什么 ---> function () {} ---> 这个事件的处理函数
 */
js 复制代码
var oDiv = document.querySelector("div");

oDiv.onclick = function () {
    console.log("你点击了 div");
};
  • 当我们点击 div 的时候, 就会执行事件处理函数内部的代码
  • 每点击一次, 就会执行一次事件处理函数

二、事件的绑定方式

  • 我们现在给一个注册事件都是使用 onXXX 的方式
  • 这种方式非常方便,是目前的主流方式,但是有一个弊端,只能给一个元素注册一个事件, 如果写了第二个, 那么第一个会被覆盖
js 复制代码
oDiv.onclick = function () {
    console.log("第一个事件");
};
oDiv.onclick = function () {
    console.log("第二个事件");
};
  • 我们这种绑定方式, 只会执行第二个, 第一个就没了
  • 如果想要两个都存在, 我们可以使用 事件监听的方式 去给元素绑定事件
  • 使用 addEventListener 的方式添加
    • 在 IE 中要使用 attachEvent

三、事件监听

1、addEventListener (非 IE7 8 下使用)

  • 语法: 元素.addEventListener('事件类型', 事件处理函数, 冒泡还是捕获)
js 复制代码
oDiv.addEventListener(
    "click",
    function () {
        console.log("我是第一个事件");
    },
    false
);
oDiv.addEventListener(
    "click",
    function () {
        console.log("我是第二个事件");
    },
    false
);
  • 点击 div 时, 两个函数都会执行, 并且会按照你书写的顺序执行
  • 先打印 我是第一个事件, 然后打印 我是第二个事件
  • 注意: 事件类型不要写 on, 点击事件就是 click, 不是 onclick

1)案例-选项卡(用let版本)

js 复制代码
     /**
         *  给 header 内的 三个 li 添加点击事件
         * 
         *  当点击到 header 内的 li 的时候, 将 content 内对应顺序的 li 展示
        */

        // var lis = document.querySelectorAll('li')    // 错误写法: 会获取到页面所有的 li
        // console.log(lis)
        var lis = document.querySelectorAll('.header li')
        var lis_c = document.querySelectorAll('.content li')

        // 这个循环只是为了给 每一个 header 内的 li 添加一个 事件, 其他没有任何用处
        for (let i = 0; i < lis.length; i++) {
            lis[i].addEventListener('click', function () {
                // 1. 取消 header 和 content 内 所有 li 的类名
                for (var k = 0; k < lis.length; k++) {
                    lis[k].className = ""
                    lis_c[k].className = ""
                }

                // 2. 给点击的 header 内的 li 添加类名
                lis[i].className = "active"

                // 3. 给对应顺序的 content 内的 li 添加类名
                lis_c[i].className = "active"

            })
        }

2)案例-选项卡(why版本)

js 复制代码
    var header = document.querySelectorAll('.header li')
    var content = document.querySelectorAll('.content li')
    for (var i = 0; i < header.length; i++) {
            header[i].dataset.index = i
            header[i].onclick = function () {
                var index = this.dataset.index
                for (var k = 0; k < header.length; k++) {
                    header[k].classList.remove('active')
                    content[k].classList.remove('active')
                }
                header[index].classList.add('active')
                content[index].classList.add('active')
            }
        }

2、attachEvent (IE 7 8 下 使用)

  • 语法: 元素.attachEvent('事件类型', 事件处理函数)
js 复制代码
oDiv.attachEvent("click", function () {
    console.log("我是第一个事件");
});
oDiv.attachEvent("click", function () {
    console.log("我是第二个事件");
});
  • 点击 div 时, 两个函数都会执行, 并且会按照你注册的顺序倒叙执行
  • 先打印 我是第二个事件, 然后打印 我是第一个事件
  • 注意: 事件类型需要要写 on, 点击事件就是 onclick

3、两个方式的区别

  • 注册事件的时候事件类型参数的书写
    • addEventListener: 需要写 on
    • attachEvent: 不需要写 on
  • 参数个数
    • addEventListener: 一般是三个常用参数
    • attachEvent: 两个参数
  • 执行顺序
    • addEventListener: 顺序注册, 顺序执行
    • attachEvent: 顺序注册, 倒叙执行
  • 适用浏览器
    • addEventListener: 非 IE 7 8 的浏览器
    • attachEvent: IE 7 8 浏览器

四、常见的事件 (了解)

  • 事件分类
    • 浏览器事件
    • 鼠标事件
    • 键盘事件
    • 表单事件
    • 触摸事件

1、浏览器事件

  • load: 页面全部资源加载完毕
  • scroll: 浏览器滚动的时候触发
  • ...

2、鼠标事件

  • click: 点击事件
  • dblclick: 双击事件
  • contextmenu: 右键事件
  • mousedown: 鼠标左键按下事件
  • mouseup: 鼠标左键抬起事件
  • mousemove: 鼠标移动
  • mouseover: 鼠标移入事件--移入子元素的时候也会触发事件
  • mouseout: 鼠标移出事件--移出子元素的时候也会触发事件
  • mouseenter: 鼠标移入事件--移入子元素的时候不会触发事件(推荐使用)
  • mouseleave: 鼠标移出事件--移出子元素的时候不会触发事件(推荐使用)
  • ...

3、键盘事件

  • 注意:不是每一个标签都可以绑定键盘事件,目前JS中只有input输入框和document对象可以绑定键盘事件
  • keyup: 键盘抬起事件
  • keydown: 键盘按下事件
  • keypress: 键盘按下再抬起事件
  • ...

4、表单事件

  • onfocus: 输入框获取焦点
  • onblur: 输入框失去焦点
  • change: 表单内容改变事件--内容改变按下回车后触发事件
  • input: 表单内容输入事件--只要内容改变就立马触发事件
  • ...

5、触摸事件

  • touchstart: 触摸开始事件
  • touchend: 触摸结束事件
  • touchmove: 触摸移动事件
  • ...

五、事件对象

  • 什么是事件对象
    • 当触发一个事件以后, 对该事件的一些描述信息
    • 比如: 点击的位置坐标是什么, 触发键盘事件时按的那个按钮
  • 每一个事件都会有一个对象来描述这些信息, 我们就把这个对象叫做 事件对象
  • 浏览器给了我们一个 黑盒子 , 叫做 window.event, 就是对事件信息的所有描述
    • 比如点击事件, 我们可以通过 event 对象知道我们点击了那个位置
js 复制代码
oDiv.onclick = function () {
    console.log(window.event.X轴坐标点信息);
    console.log(window.event.Y轴坐标点信息);
};
  • 但这东西有兼容性问题, 在低版本IE里很好用, 但是在高版本IE和Chrome 里不好使了
  • 所以我们需要换一个方式来获取, 就是在每一个事件处理函数的形参位置, 默认第一个就是 事件对象
js 复制代码
oDiv.onclick = function (e) {
    console.log(e.X轴坐标点信息);
    console.log(e.Y轴坐标点信息);
};
  • 综上所述, 我们以后在每一个事件里, 都采用兼容写法
js 复制代码
oDiv.onclick = function (e) {
    e = e || window.event;
    console.log(e.X轴坐标点信息);
    console.log(e.Y轴坐标点信息);
};

六、点击事件的光标点获取

  • 我们点击事件的坐标点都不是一堆, 所以要有一个相对的坐标系
  • 例如:
    • 相对于事件源(就是我们点击的那个元素)
    • 相对于页面
    • 相对于浏览器窗口
  • 因为这些都不一样, 所以我们获取的方式也不一样

1、相对于事件源

  • offsetX 和 offsetY
  • 相对于我们点击的元素的边框内测开始计算
js 复制代码
* {
	margin: 0;
	padding: 0;
}
div {
	width: 300px;
	height: 300px;
	padding: 20px;
	border: 10px solid #333;
	margin: 20px 0 0 30px;
}

<div></div>

var oDiv = document.querySelector('div')

// 注册点击事件
oDiv.onclick = function (e) {
	// 事件对象兼容写法
	e = e || window.event

	console.log(e.offsetX)
	console.log(e.offsetY)
}

2、相对于浏览器窗口你点击的坐标点

  • clientX 和 clientY
  • 相对于浏览器窗口来计算的, 不管你页面滚动到什么情况, 都是根据窗口来计算坐标
js 复制代码
* {
	margin: 0;
	padding: 0;
}
body {
	width: 2000px;
	height: 2000px;
}
div {
	width: 300px;
	height: 300px;
	padding: 20px;
	border: 10px solid #333;
	margin: 20px 0 0 30px;
}

<div></div>

var oDiv = document.querySelector('div')

// 注册点击事件
oDiv.onclick = function (e) {
	// 事件对象兼容写法
	e = e || window.event

	console.log(e.clientX)
	console.log(e.clientY)
}

3、相对于页面你点击的坐标点

  • pageX 和 pageY
  • 是相对于整个页面的坐标点, 不管有没有滚动, 都是相对于页面拿到的坐标点
js 复制代码
* {
	margin: 0;
	padding: 0;
}
body {
	width: 2000px;
	height: 2000px;
}
div {
	width: 300px;
	height: 300px;
	padding: 20px;
	border: 10px solid #333;
	margin: 20px 0 0 30px;
}

<div></div>

var oDiv = document.querySelector('div')

// 注册点击事件
oDiv.onclick = function (e) {
	// 事件对象兼容写法
	e = e || window.event

	console.log(e.pageX)
	console.log(e.pageY)
}

七、获取键盘按键

  • e.key直接返回按下的键;e.keyCode返回的是按键对应的数字编码
js 复制代码
    var inp = document.querySelector('#inp')
        inp.onkeyup = function () {
            console.log(e.key,e.keyCode)
        }

八、鼠标拖拽案例

js 复制代码
      var box = document.querySelector('.box')
        /**
         *  思考:
         *  
         *      1. 需要什么事件?
         *          1.1 按下
         *          1.2 移动
         *          1.3 抬起
         *      2. 谁是事件源?
         *          2.1 box
         *          2.2 box / document
         *          2.3 box
         * 
         *      3. 移动的距离?
         *          3.1 获取最新的鼠标定位 - 鼠标按下时的定位 === 移动距离
         *          证明: 初始定位 x和y 都是 50         移动到了 x和y 的值为 150
         * 
         *      4. 移动到哪里?
         *          4.1 元素的初始位置 + 移动的距离 === 移动到哪里
         *          证明: 元素初始位置 x和y 都是 50         移动距离 x和y 都移动 100
        */

        var flag = false

        // 保存鼠标按下时的 定位
        var startX = 0
        var startY = 0

        // 保存鼠标按下时的 位置(偏移量)
        var startLeft = 0
        var startTop = 0

        box.onmousedown = function (e) {
            flag = true
            // console.log('鼠标按下', e.clientX, e.clientY)

            // 按下时 保存 鼠标的定位
            startX = e.clientX
            startY = e.clientY

            // 按下时 保存 元素的偏移量
            startLeft = box.offsetLeft
            startTop = e.target.offsetTop
        }



        document.onmousemove = function (e) {
            if (!flag) return
            // console.log('鼠标移动前的定位', startX, startY)
            // console.log('鼠标移动后的定位', e.clientX, e.clientY)

            // 3.1 获取最新的鼠标定位 - 鼠标按下时的定位 === 移动距离
            var moveX = e.clientX - startX
            var moveY = e.clientY - startY

            // 4.1 元素的初始位置 + 移动的距离 === 移动到哪里
            var left = startLeft + moveX
            var top = startTop + moveY

            if (left <= 0) left = 0
            if (left >= document.documentElement.clientWidth - box.offsetWidth) left = document.documentElement.clientWidth - box.offsetWidth
            if (top <= 0) top = 0
            if (top >= document.documentElement.clientHeight - box.offsetHeight) top = document.documentElement.clientHeight - box.offsetHeight

            box.style.left = left + 'px'
            box.style.top = top + 'px'
        }



        box.onmouseup = function () {
            flag = false
            console.log('鼠标抬起')
        }
相关推荐
牛蛙点点申请出战17 分钟前
IconFontViewer -- 一个可以在 Android Studio 中实时预览 IconFont 的插件
android·前端·intellij idea
空中海18 分钟前
03 渲染机制、性能优化与现代 React
javascript·react.js·性能优化
ChalesXavier1 小时前
Fetch API 的基本用法
javascript
是上好佳佳佳呀1 小时前
【前端(十三)】JavaScript 数组与字符串笔记
前端·javascript·笔记
巴沟旮旯儿1 小时前
vite项目配置文件和打包
前端·设计模式
彩票管理中心秘书长1 小时前
Pinia 插件架构与组合式函数:如何让你的 Store 长出“超能力”
前端
彩票管理中心秘书长1 小时前
Pinia 比 Vuex 强在哪?我用同一个模块写了两种实现,你自己看
前端
yingyima1 小时前
用 Cron 加 Webhook 打通自动化工作的任督二脉
前端
JackieDYH1 小时前
CSS Flexbox 与 Grid 的默认行为-布局的底层机制
前端·css·html
彩票管理中心秘书长1 小时前
E2E测试入门:别让用户帮你点鼠标了,找个机器人替你打工吧
前端