day11 事件

事件

概述:

事件是一个异步机制。他相当于一个 执行者执行 – 观察者观察 — 处理函数执行 这个流程称为事件。

事件的组成
  • 事件名 (内置的)
  • 执行对象 (元素对象)
  • 处理函数 (自定义函数)
  • 观察者 (js的事件引擎)
示例
<button>点击</button>
button.onclick = function(){
	console.log('点击了')
}

事件名 click(内置的)

执行对象 button (元素对象)

处理函数 后续的函数 (自定义函数)

观察者 (js引擎 事件引擎)

在js内书写的事件,他的观察者都是事件引擎。 我们需要关注就是前面的三个内容(事件名、执行对象、处理函数)

事件的声明书写方式

内联模式(在标签内部)
<!-- 内联模式就是在onclick书写中设置对应的代码 -->
<button onclick="alert('你好')">点我</button>
<button onclick="fn(1)">点我</button>
<script>
    function fn(arg){
        alert('我是函数执行'+arg);
    }
</script>
脚本模式 (在script中 常用)
//脚本模式的写法 事件名 执行对象 处理函数
var btn = document.getElementsByTagName('button')[2]
//执行对象.on+事件名 = 处理函数
btn.onclick = function(){
    console.log('你好');
}
function handler(){
    console.log('处理函数执行了');
}
btn.onclick = handler
内联模式和脚本模式的区别
  • 内联模式里面的函数需要手动调用 而对应的脚本的模式的处理函数自动调用
  • 内联模式里面的函数调用的this指向window 对应的脚本模式里面的处理函数的this指向当前的调用者

事件名的分类

鼠标事件(鼠标触发的 mouse)
  • click 单击事件
  • dblclick 双击事件
  • mousedown 按下
  • mouseup 弹起
  • mouseenter 移入
  • mouseleave 移出
  • mouseover 移入
  • mouseout 移出
  • mousemove 移动
  • contextmenu 右键点击
注意事项
  • click和对应mousedown和mouseup的执行顺序 (mousedown – mouseup – click)
  • mouseenter(mouseleave)和mouseover(mouseout)的区别 (mouseenter 子元素不会触发 mouseover子元素会触发)
<div>我是一个div
    <p>你好</p>
</div>
<script>
    //获取div
    var div = document.querySelector('div')
    //脚本模式 元素对象.on+事件名 = 处理函数
    div.onclick = function(){
        console.log('单击事件执行了');
    }
    //双击事件必定触发单击
    div.ondblclick = function(){
        console.log('双击事件执行了');
    }
    //鼠标的按下和弹起  执行顺序 按下 -- 弹起 -- 单击
    div.onmousedown = function(){
        console.log('鼠标按下');
    }
    div.onmouseup = function(){
        console.log('鼠标弹起');
    }
    //鼠标的移进和移出
    //enter和leave 进入子元素不会触发
    div.onmouseenter = function(){
        console.log('鼠标移进去了');
    }
    div.onmouseleave = function(){
        console.log('鼠标移出了');
    }
    //over和out 进入子元素也会触发
    div.onmouseover = function(){
        console.log('鼠标over移入了');
    }
    div.onmouseout = function(){
        console.log('鼠标out移出了');
    }
    //鼠标的移动
    div.onmousemove = function(){
        console.log('鼠标移动了');
    }
    //鼠标点击右键 (点击事件不会触发)
    div.oncontextmenu = function(){
        console.log('右键点击了');
    }
</script>
键盘事件 (键盘触发的 key)

keydown 按下

keyup 弹起

keypress 字符串键(除功能键的其他键)

<input type="text">
<script>
    //获取输入框
    var input = document.querySelector('input')
    //键盘相关事件
    input.onkeydown = function(){
        console.log('键盘按下');
    }
    //在input 弹起会出现俩次
    input.onkeyup = function(){
        console.log('键盘弹起');
    }
    //字符键按下 (除了功能键)
    input.onkeypress = function(){
        console.log('字符键按下');
    }
    window.onkeypress = function(){
        console.log('在window上触发了keypress事件');
    }
</script>
注意事项
  • 执行顺序 keydown - keypress - keyup
  • keypress 一定会触发 keydown
HTML事件 (HTML中自带的一些事件(只能用于专门HTML))
window的事件
  • 加载事件(load)
  • 卸载事件 (unload)
  • 关闭窗口的事件 (onclose)
  • 打印之前调用的事件 (onbeforeprint)
  • 卸载之前调用的事件 (onbeforeunload)
  • 滚动栏发生变化的事件 (onscroll)
//加载事件
window.onload = function(){
    console.log('hello');
}
//卸载事件(刷新)
window.onunload = function(){
    console.log('卸载');
}
//关闭窗口事件 (清除相关缓存和对应的资源操作)
window.onclose = function(){
    console.log('关闭');
}
//打印之前调用 调用print方法之前 更改打印的然后继续打印
window.onbeforeprint = function(){
    console.log('打印了');
}
//在卸载之前调用 将一些内容回收
window.onbeforeunload = function(){
    console.log('卸载之前');
}
//滚动栏滚动
window.onscroll = function(){
    console.log('滚动栏位置发生变化');
}
//加载事件的其他使用
var image = new Image() //构建一个图片对象
image.onload = function(){ //如果图片加载好了
    image.src = '图片地址' //给图片设置对应的src地址
}
//onscroll的其他使用
document.querySelector('div').onscroll = function(){
    console.log('div的滚动栏滚动了');
}
表单的事件
  • submit 表单提交事件
  • reset 表单重置事件
  • select 内容被选中(只针对于输入框和文本域)
  • change 表单的value值发生变化
  • input 可输入的表单标签里面进行输入
  • blur 失去焦点
  • focus 获取焦点
//表单相关的事件
//加给整个form表单的事件
document.forms[0].onsubmit = function(){
    console.log('提交了');
}
document.forms[0].onreset = function(){
    console.log('重置了');
}
//change value值发生变化 失去焦点
document.querySelector('input').onchange = function(){
    console.log('值变化了');
}
// input 输入对应的值的时候调用
document.querySelector('input').oninput = function(){
    console.log('输入值');
}
//select 选择里面的内容
document.querySelector('input').onselect = function(){
    console.log('选择值了');
}
//失去焦点
document.querySelector('input').onblur = function(){
    console.log('失去焦点了');
}
//聚焦
document.querySelector('input').onfocus = function(){
    console.log('获取焦点了');
}
相关聚焦和失焦的方法
  • focus 聚焦的方法
  • blur 失焦的方法
//element也具备 focus() blur()
document.querySelector('input').focus()
setTimeout(function(){
    document.querySelector('input').blur()
},3000)

event 事件源对象

概述

event 被称为事件源对象,他是一个全局的内置对象(属于window),他里面包含了一些关于事件执行的相关的属性。

处理函数中Arguments

处理函数也是一个函数,函数就具备一个arguments的属性。argments是一个伪数组。那么就可以知道对应的处理函数里面也拥有arguments

var btn = document.querySelector('button')
btn.onclick = function(){
    //点击事件触发以后对应的arguments里面有一个对应的pointEvent的对象
    console.log('arguments',arguments);
    console.log(`arguments[0]`, arguments[0]);
    //这个对象是在arguments里面存在第一位里面以属性为主 那么这个对象表示什么
    //这个参数其实就对应的事件的一些内容 称为事件源对象 event
}
window.onkeydown = function(){
    console.log('arguments',arguments);
    //keyboardEvent 键盘的事件源对象
    console.log(`arguments[0]`, arguments[0]);
}

从上述代码可得到对应的事件执行的处理函数里面会传递一个参数 ,这个参数的类型是一个event。这个处理函数的arguments数组里面只有一个元素。

故而我们可以简写为

//这个地方的e 一般写做 e 或者是 event
btn.onclick = function(e){
    //这个地方的e表示是第一个参数 也就是对应的event对象 这个event在这个里面有兼容问题
    //兼容写法
    e = e || window.event
    //这个e表示的就是第一个参数 那么他也就是我们对应的event对象
    console.log(`e`, e);
}

event的常用属性

鼠标坐标的相关属性
  • screenX 表示鼠标离屏幕的X距离
  • screenY 表示鼠标离屏幕的Y距离
  • pageX 表示当前的鼠标离页面的X距离(包含卷起部分)
  • pageY 表示当前的鼠标离页面的Y距离(包含卷起部分)
  • clientX 表示鼠标离页面可视区的X距离
  • clientY 表示鼠标离页面可视区的Y距离
  • offsetX 表示鼠标离父元素偏移的X距离
  • offsetY 表示鼠标离父元素偏移的Y距离

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d92WDQhI-1669819486125)(C:\Users\29769\AppData\Roaming\Typora\typora-user-images\image-20221013163327515.png)]

按钮辅助的相关属性
  • ctrlKey 是否按下了ctrl键
  • altKey 是否按下了alt键
  • shiftKey 是否按下shift键
//辅助的按键属性 返回布尔类型值
console.log(e.ctrlKey);//是否长按ctrl
console.log(e.altKey);//是否长按alt
console.log(e.shiftKey);//是否长按shift
鼠标相关的属性
  • button 按下是那个键
//按下的键是什么 三个值 0 1 2
console.log(e.button);//左键0 中间滚轮1 右键2
事件及相关触发的属性
  • type 当前的事件类型
//事件类型 返回事件名
console.log(e.type); //click
  • target 表示当前事件的触发对象
  • currentTarget 表示加事件的元素
//触发者元素
console.log(e.target);
//加事件的元素
console.log(e.currentTarget);
键盘相关的属性
  • key 表示当前按下的键的字符(区分大小写)
  • keyCode (在keydown里面 不区分大小 全部是大写的ascii码)
  • code (key+大写的字符)
  • charCode (在keypress里面才管用 他区分大小写 返回对应的ascii码)
window.onkeypress = function(e){
    console.log(e.code);//当前的按钮按下键是哪个一个 返回的是一个key+大写字母
    console.log(e.keyCode);//当前按下键的大写字母 ascii码
    console.log(e.charCode); //当前字符的ascii码 keypress里面
    console.log(e.key);//表示当前按下的键 (兼容问题)
}

事件委托机制(事件代理)

概述:将对应的事件委托给对应的父元素,然后通过对应的e.target获取实际的触发元素进行操作。

示例
//事件委托的写法
//获取需要加事件的父元素
var ul = document.querySelector('ul')
//给ul添加事件
//给父元素添加事件
//在内部判断触发元素 e.target
//对应执行操作
ul.onclick = function (e) {
    e = e || window.event
    //判断当前触发元素是否为li
    if (e.target.tagName == 'LI') {
        //排他思想
        //把所有的li的class清除
        for (var item of this.children) {
            item.className = ''
        }
        e.target.className = 'active'
    }
}
事件委托的运用场景

在一个父元素里面有多个子元素要添加相同的事件的时候

事件的传播行为(事件流)

冒泡模式(默认模式)

冒泡模式就是从里到外触发

event.bubbles(只读属性)
console.log(e.bubbles);//当前事件是否冒泡
<div>
    <button>点我</button>
</div>
<script>
    //点击按钮 先触发按钮的点击事件 然后触发div的点击事件 然后触发document的点击事件
    document.onclick = function(){
        console.log('文档被点击了');
    }
    document.querySelector('div').onclick = function(){
        console.log('div被点击了');
    }
    document.querySelector('button').onclick = function(e){
        console.log(e.bubbles);//当前事件是否冒泡
        console.log('button被点击了');
    }
</script>
阻止事件冒泡
  • stopPropagation (方法)
e.stopPropagation() //阻止事件冒泡 常用的方法 兼容问题 
  • 兼容ie低版本的写法 cancelBubble (属性)
// 兼容写法  兼容ie8及以下
e.cancelBubble = true
  • 兼容写法
//兼容写法
e.stopPropagation?e.stopPropagation():e.cancelBubble = true
捕获模式

捕获模式就从外到里触发

默认行为

某些操作或者html元素拥有的一些默认的行为(a 标签的默认行为 进行页面跳转 form里面submit行为 图片的拖动行为…)

在某些时候外面的默认行为会导致对应的代码执行出现问题,这个时候就需要禁止默认行为。

阻止默认行为
  • preventDefault (方法)
//阻止默认行为
e.preventDefault();//大部分浏览器兼容
  • 兼容ie低版本的写法 returnValue 属性
 //兼容ie
e.returnValue = false //兼容ie
  • 兼容写法
e.preventDefault?e.preventDefault():e.returnValue = false
  • return false
return false

事件监听器(兼容问题)

  • addEventListener 添加事件监听器(可以添加多个处理函数)
  • removeEventListener 移除事件监听器 (只能移除addEventListener添加的 移除根据对应的处理函数是否为一个)
//我需要俩个处理函数 事件监听器 可以有多个处理函数
//监听对应的事件执行 来执行对应的处理函数 (不会覆盖之前的事件的处理函数)
//传入事件名 传入处理函数 (如果是直接传入function 就不会被移除)
btn.addEventListener('click',function(){
    console.log('点击了按钮');
})
btn.addEventListener('click',function fn(){
    console.log('点击了按钮1');
})
btn.addEventListener('click',handler1)
//移除事件监听器 必须处理函数是同一个 不然不能被移除 只能移除addEventListener添加的
btn.removeEventListener('click',function fn(){
    console.log('点击了按钮1');
})//不能移除
btn.removeEventListener('click',handler1) //能
btn.removeEventListener('click',handler)//不能移除

拖拽

基础三大事件
  1. 鼠标按下事件 (mousedown)
  2. 鼠标移动事件 (mousemove)
  3. 鼠标弹起事件 (mouseup)
在页面进行拖拽
步骤
  1. 给对应的盒子添加鼠标按下事件
  2. 在鼠标按下事件内容获取鼠标在对应盒子里面的位置 (offsetX)
  3. 在鼠标按下事件中给document添加移动事件
  4. 在移动的时候获取鼠标在页面上的位置(pageX)
  5. 计算对应的定位的位置 (鼠标在页面上的位置 - 鼠标在对应盒子内的位置)
  6. 设置对应的盒子的位置
  7. 在鼠标按下事件中给document添加弹起事件
  8. 在弹起事件内移除对应的移动事件
<div></div>
<script>
    //获取div
    var div = document.querySelector('div')
    //在div里面按下
    div.onmousedown = function(e){
        e = e || window.event
        //获取按下时 鼠标在对应盒子里面位置
        var currentX = e.offsetX
        var currentY= e.offsetY
        //在文档里面移动
        document.onmousemove = function(e){
            //获取每次移动在页面上的位置 - 对应的按下时鼠标在盒子里面的位置 = 对应的定位的位置
            var targetX = e.pageX - currentX
            var targetY = e.pageY- currentY
            //设置给对应的盒子
            div.style.left =  targetX + 'px'
            div.style.top =  targetY + 'px'
        }
        //在文档里面弹起
        document.onmouseup = function(){
            document.onmousemove = null
        }
    }
</script>
在区间进行拖拽
offset家族(属性 元素对象)
  • offsetParent 偏移父元素 (找离最近的定位父元素 如果没有定位就找body)
  • offsetHeight 偏移元素的高度
  • offsetWidth 偏移元素的宽度
  • offsetLeft 离父元素偏移的左边的距离 (number类型)
  • offsetTop 离父元素偏移的上边距离 (number类型)
<div class="outerBox">
    <div class="box">
        <div class="moveBox"></div>
    </div>
</div>
<script>
    //获取移动的盒子
    var move = document.querySelector('.moveBox')
    //获取区间的大盒子
    var box = document.querySelector('.box')
    //给移动的盒子添加按下事件
    move.onmousedown = function (e) {
        //获取在移动的盒子里面按下的位置
        e = e || window.event
        var currentX = e.offsetX
        var currentY = e.offsetY
        //给区间的大盒子添加移动
        box.onmousemove = function (e) {
            e = e || window.event
            //设置move这个盒子在box里面定位 
            //鼠标在页面的位置 e.pageX  - 大盒子在页面的位置 - 鼠标按下的位置 currentX
            var distance = computedPointElementInPage(this)
            //接收对应的设置的定位位置
            var targetX =  e.pageX - distance.left - currentX
            var targetY = e.pageY - distance.top - currentY
            //进行区间判断
            //最大的移动距离X = 大盒子宽度 - 小盒子的宽度
            var maxX =  this.offsetWidth - move.offsetWidth
            var maxY =  this.offsetHeight - move.offsetHeight
            //如果当前的定位位置比0还小 设置为0
            if(targetX < 0){
                targetX = 0
            }
            if(targetY < 0){
                targetY = 0
            }
            //如果比最大值还大 就设置最大值
            if(targetX > maxX){
                targetX = maxX
            }
            if(targetY > maxY){
                targetY = maxY
            }
            //位置设置
            move.style.left =  targetX + 'px'
            move.style.top =   targetY + 'px'
        }
        document.onmouseup = function(){
            //清除大盒子的移动事件
            box.onmousemove = null
        }
    }
    //如果要找盒子在页面上的位置 那么外面要从自己的基于的父元素的距离 + 对应父元素基于他的父元素距离 .. 直到找到body
    //封装一个方法计算盒子在页面上的位置 传递一个盒子
    function computedPointElementInPage(element) {
        //封装一个距离对象 left离左边的 top离上边的
        var distance = {
            left: 0,
            top: 0
        }
        //到了body就是null 到了body对应while循环就结束
        while (element.offsetParent) {
            //将对应的左边的距离一个个+
            distance.left += element.offsetLeft
            //将对应的上边的距离一个个+
            distance.top += element.offsetTop
            //进入到父元素
            element = element.offsetParent
        }
        //将计算好的结果返回出去
        return distance
    }
</script>

样式获取

  • style属性 只能获取内嵌样式

    var div = document.getElementsByTagName('div')[0]
    //style的弊端 他只能获取对应的内嵌的样式 也就是只能获取style属性里面写的内容
    console.log(div.style.width); //空字符串
    console.log(div.style.height); //300px
    
  • getComputedStyle 方法可以获取所有的样式

    //对应的兼容获取所有样式的方法
    var style = getComputedStyle(div, '')
    console.log(style); //getComputedStyle获取样式对象里面都有默认值(所有的样式)
    console.log(style.backgroundColor);
    console.log(style.color);
    console.log(style.width);
    console.log(style.height);
    
  • currentStyle ie的低版本兼容

    console.log(div.currentStyle); //ie低版本兼容 废弃
    
  • 兼容封装

    // getComputedStyle 兼容问题 
    // console.log(div.currentStyle); //ie低版本兼容 废弃
    //兼容写法 传入一个元素 返回一个样式对象
    function getStyle(element) {
        var style = window.getComputedStyle ? getComputedStyle(element, '') : element.currentStyle
        return style
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值