事件

事件

事件概念

用户在浏览器上触发的一个操作,浏览器上会执行相关的函数进行处理,这个称之为事件。例如用户点击登录按钮,浏览器会完成的登录操作。

事件组成

触发者.on+事件名 = 执行函数

  1. 触发事件对应的元素对象
  2. 事件类型(下述分类的事件类型)
  3. 事件执行函数 (有自己定义的函数,该函数是由事件驱动执行的)
//单击文档的任意位置
document.onclick = function(){
    console.log('事件触发')
};

注:事件处理函数一般都是小写字母

事件模式

1.内联模式

直接在HTML标签中添加事件

<button conclick = "alert(123)">123</button>

2.脚本模式

将对应的事件的处理函数进行分离

<button conclick = "handlerClick()">123</button>
<script>
    handlerClick(){
       alert(123)
    }
</script>

内联模式里面调用的方法的this会指向window(传递this)脚本模式的this会指向当前的调用者

事件类型

在事件对象中有个一个属性 type 可以获取到当前事件的类型。

window.onload = function(e){
    var ev = e || window.event; 
    console.log(ev.type); // load 
}

1.鼠标事件

事件 描述
click 左键单击
contextmenu 右键单击(不会触发点击事件)
dblclick 双击
mousedown 左键按下
mouseup 左键弹起
mouseover 鼠标移入(其中的子元素上也会触发)
mouseout 鼠标离开(其中的子元素也能够触发)
mouseenter 鼠标移入(只会自己触发)
mouseleave 鼠标离开(只会自己触发)
mousemove 鼠标移动
mousewheel 鼠标滚轮事件

鼠标滚轮事件有兼容性问题,在IE、Chrom中是mousewheel,在FireFox中是DOMMouseScroll,且在 FireFox中不能使用on来绑定。在IE和Chrome中向上滚动,事件对象中的wheelDelta是120,向下滚动是-120,在 FirFox中向上滚动,事件对象中的e.detail是3,向下滚动是-3。

2.键盘事件

事件 描述
keydown 键盘按下(若按住不放,会重复触发)
keyup 键盘弹起(若按住不放,会重复触发)
keypress 字符键按下

键盘事件除了用window可以触发之外,还可以使用document,或者表单元素,总之是可以选中的元素。例如div就不行。我们操作时,除非是输入框,否则不能调用键盘事件。

//keydown
window.onkeydown = function() {
        console.log('按下了键盘上的某个键'); 
};
//keypress
window.onkeypress = function() { 
        console.log('按下了键盘上的字符键'); 
};
//keyup
window.onkeyup = function() {
        console.log('松开键盘上的某个键'); 
};

3.HTML事件

浏览器事件
事件 描述
load 加载
unload 关闭
scroll 滚动
resize 大小改变
表单事件
事件 描述
submit 提交表单
focus 获取焦点
blur 失去焦点
change 内容改变并失去焦点
input input的value值改变
select 输入框触发(选择里面的内容)

input事件在低版本的IE中不兼容,使用 onpropertychange 代替

// load  窗口的加载 图片的加载 等等
window.onload = function(){
    console.log('窗口加载');
}
window.onunload = function(){ //清除对应的内存 销毁
    console.log('窗口卸载');
}
window.onclose = function(){
    console.log('窗口关闭');
}
var input = document.querySelector('input')
input.onchange = function(){ //必须要失去焦点
    console.log('value值变化了');
}
input.onselect = function(){ //禁止复制粘贴
    console.log('当前内容被选择');
}
input.onfocus = function(){
    console.log('获取焦点');
}
input.onblur = function(){
    console.log('失去焦点');
}
//scroll 滚动栏 滚动事件
window.onscroll = function(){ //每次滚动距离
    console.log('滚动条滚动');
}
//表单元素获取焦点事件
document.querySelector("input").onfocus = function(){
    console.log("获取焦点");
    // focus方法可以直接获取焦点
    document.querySelector("input:nth-child(2)").focus()
}
// 表单元素失去焦点事件
document.querySelector("input").onblur = function(){
    console.log("失去焦点");
}
document.querySelector("#context").onselect = function(){
    console.log("选择了");
}
// 修改数据 修改数据 失去焦点
document.querySelector("input:nth-child(2)").onchange = function(){
    console.log("修改数据了");
}
//vue 双向绑定的原理实现
document.querySelector("input:nth-child(2)").oninput = function(){
    console.log("输入数据");
}
// form表单的事件 onsubmit 提交的时候触发 onreset 重置的时候的触发
document.querySelector('form').onsubmit = function(){
    console.log('表单提交');
}
document.querySelector('form').onreset = function(){
    console.log('表单重置');
}

所有的函数都具备一个参数arguments(所有传递参数是数组)

对应的arguments里面只有一个参数且这个参数是event对象(事件源对象)

arguments[0]是或者对应的arguments数组里面的第一个参数(第一个形参 故在对应的处理函数中直接声明一个形参来接收arguments里面的数据)

// document.querySelector("button").onclick = function(){
//     //作为处理函数来说 他同样也是个函数 那么他就存在着一个arguments数组 获取对应的参数
//     console.log(arguments); //他里面只有有个参数 这个参数 pointerEvent
//     console.log(arguments[0].altKey);//是否按下的alt键
//     console.log(arguments[0].ctrlKey);//是否按下了ctrl键
//     console.log(arguments[0].shiftKey);//是否按下了shiftKey键
//     console.log(arguments[0].button);//鼠标的按键 左0 中间的为1 右2
//     console.log(arguments[0].type);//对应的触发事件类型
//     console.log(arguments[0].x);//鼠标的x位置
//     console.log(arguments[0].y);//鼠标的y位置
// }
document.querySelector("button").onclick = function(e){
    //e其实就是我们对应的arguments[0] 所以这个e就是我们的event对象
    // 建议形参的写法为 e或event
    //兼容写法
    e = e || window.event //兼容写法
    console.log(e.altKey);
}
window.onkeydown = function(){
    console.log(arguments); //他里面同样只有一个参数 这个参数为 keyboardEvent
    console.log(arguments[0].altKey);
    console.log(arguments[0].ctrlKey);
    console.log(arguments[0].type);
}
//arguments里面存放的内容就是我们对应的event (事件源对象)

事件对象Event

概述

event对象是在触发事件时, 浏览器会通过函数把事件对象作为参数传递过来, 在事件触发执行函数时一般会得到一个隐藏的参数, 该参数也是放在arguments数组中。

通过事件绑定的执行函数是可以得到一个隐藏参数的. 说明浏览器会自动分配一个参数,这个隐藏参数其实就是event对象(事件对象)。

位置属性

x 得到鼠标的x坐标(不包含不可视区域)

y 得到鼠标的y坐标(不包含不可视区域)

offsetX 鼠标离当前元素的X距离

offsetY 鼠标离当前元素的Y距离

clientX 鼠标离网页最左的距离 (不包含不可见部分)

clientY 鼠标离网页最顶部的距离 (不包含不可见部分)

pageX 鼠标离网页最左的距离 (包含不可见部分)

pageY 鼠标离网页最顶部的距离 (包含不可见部分)

screenX 鼠标离屏幕最左部的距离

screenY 鼠标离屏幕最顶部的距离

layerX 默认是以body作为位置定位的X坐标 当加上定位以后就是基于定位元素的坐标

layerY 默认是以body作为位置定位的Y坐标 当加上定位以后就是基于定位元素的坐标

//event中的属性
//位置属性
console.log(e.x);//当前鼠标离对应的最顶部的距离(不包含滚动栏的距离)不包含不可见距离
console.log(e.y);
console.log(e.clientX);
console.log(e.clientY);
console.log(e.offsetX);//对应在div里面的鼠标位置X
console.log(e.offsetY);//对应在div里面的鼠标位置Y
console.log(e.pageX);//当前鼠标离对应的最顶部的距离(包含滚动栏的距离) 包含不可见距离
console.log(e.pageY);
console.log(e.layerX);//在定位的时候基于自己 不定位的时候基于最顶部距离  包含不可见距离
console.log(e.layerY);
console.log(e.screenX);//离屏幕最坐标的X距离
console.log(e.screenY);//离屏幕最上面的y距离
按键属性

ctrlKey —— 是否按下ctrl键

altKey —— 是否按下alt键

shiftKey —— 是否按下shift键

//三个按键是否按下(长按) 先按下再操作 布尔类型的值
console.log(e.ctrlKey); //是否按下ctrl
console.log(e.shiftKey);//是否按下shift
console.log(e.altKey);//是否按下alt
鼠标相关内容(只有鼠标触发的事件)

button —— 点击的鼠标的那个键(左键0 中间1 右键2)

console.log(e.button); //点击的鼠标的那个键(返回的是number类型)
键盘输入属性(需要键盘触发的事件)

key —— 获取对应的按下的键

keyCode —— 获取按下的键的ascii码

charCode —— 获取keypress事件中按键的ascii码

window.onkeydown = function(e){
    //兼容 ie
    e = e || window.event
    console.log(e);
    //key 获取对应的按下的键
    console.log(e.key);//兼容问题
    //keyCode 获取对应按下键的ascii码
    console.log(e.keyCode); //不管是大写还是小写获取的都是大写的ascii码
}
//只支持字符
window.onkeypress = function(e){
    console.log(e.keyCode);
    //将ascii转为对应的字符串
    console.log(String.fromCharCode(e.keyCode));
    //只在onkeypress 里面才有用 也返回是ascii码
    console.log(e.charCode);
}
其他属性

type —— 事件触发类型

target —— 当前触发事件的对象

currentTarget —— 当前添加事件的对象

console.log(e.type); //事件触发的类型 
//target 目标对象
console.log(e.target); //当前触发的对象 
console.log(e.currentTarget); //当前添加事件的对象

事件流

阻止事件冒泡和默认行为

事件冒泡

概念:从里到外冒泡 里面有一个按钮添加了点击事件 外面有个盒子也添加了点击事件 在你触发对应的按钮的点击的时候 同时他会自动调用对应盒子的点击事件 而这个机制就叫做事件冒泡

事件捕获

从外向里逐渐触发

阻止事件冒泡

e.stoppropagation() *

e.cancelBubble = true (兼容ie的写法)

document.querySelector("div").onclick = function(){
    console.log("大盒子被点击了");
}
document.querySelector("button").onclick = function(e){
    e = e || window.event
    // // 阻止事件冒泡
    // e.stopPropagation() //适用大多数的浏览器 *
    // //兼容ie 取消冒泡
    // e.cancelBubble = true
    //兼容写法
    if(e.stopPropagation){
        e.stopPropagation()
    }else{
        e.cancelBubble = true
    }
//三目运算写法
    e.stopPropagation?e.stopPropagation():e.cancelBubble = true
    console.log("按钮被点击了");
}
默认行为

就是一个元素会自带的行为称为默认行为 a标签的默认行为会跳转 form标签里面submit按钮默认会提交(刷新页面)鼠标右键会出现一个菜单栏等等一系列的问题

阻止默认行为

元素自身拥有的一些行为

form的submit按钮会自动提交 然后跳转页面

a标签 直接默认跳转页面

鼠标右键点击 会出现菜单栏

......

e.preventDefault() 适用所有符合w3c规则的浏览器 *

e.returnValue = false 适用ie浏览器 同样适用于高版本浏览器(可能会被废弃)

return false 直接结束对应的操作 都适用

//阻止a标签默认跳转的行为
<a href="http://www.baidu.com">百度</a>
<script>
    document.querySelector("a").onclick = function(e){
    e = e || window.event
    //阻止a标签默认跳转的行为
    // e.preventDefault() //阻止默认行为 *
    //ie浏览器兼容
    // e.returnValue = false //阻止默认行为 returnValue 同样适用于高版本浏览器(可能会被废弃)
    console.log("a标签被点击了");
    return false //阻止默认行为 一般写在最后
}
</script>
右击菜单栏事件
document.oncontextmenu

事件委托机制

将原本元素需要做的事件 交给他的父元素

1.加事件给对应的父元素

2.在父元素的事件中进行判断 e.target

//选中效果
// 先获取所有的li
//    var lis =  document.querySelectorAll("li")
//     // 再给对应的li添加事件
//     for(var i=0;i<lis.length;i++){
//         // 在事件里面进行操作
//         lis[i].onclick = function(){
//             //排他思想
//             for(var j=0;j<this.parentElement.children.length;j++){
//                 this.parentElement.children[j].style.backgroundColor = ""
//             }
//             this.style.backgroundColor = "red"
//         }
//     }
//事件委托 (里面有多个相同的元素需要同样的事件)
//获取父元素 利用的父元素的事件及对应的e.target进行判断 当前你操作的元素是哪一个
document.querySelector("ul").onclick = function(e){
    e = e || window.event
    //获取当前操作的元素 li
    if(e.target.nodeName == "LI"){
        //操作
        //排他思想
        for(var j=0;j<this.children.length;j++){
            this.children[j].style.backgroundColor = ""
        }
        e.target.style.backgroundColor = "red"
    }

}

拖拽

  • 鼠标按下 mousedown (获取点击在元素上的位置)
  • 鼠标移动 mousemove (获取在文档上移动的位置 控制对应的元素移动)
  • 鼠标弹起 mouseup (将弹起事件和移动事件清除)
<!-- 在body里面拖拽 位置会改变 拖拽的元素需要定位 -->
<div></div>
<script>
    //1.获取div元素
    var div = document.querySelector("div")
    //2.需要给div的元素添加鼠标按下事件(获取按下在元素里面的位置)
    div.onmousedown = function(e){
        e = e || window.event
        //需要对应的鼠标在盒子里的位置 offsetX offsetY
        var currentX = e.offsetX
        var currentY = e.offsetY
        //3.在按下事件里面添加移动事件 (获取移动的位置) 新的位置-鼠标在盒子里面点击的位置
        document.onmousemove = function(e){
            e = e || window.event
            var targetX = e.pageX - currentX //移动的距离
            var targetY = e.pageY - currentY //移动的距离
            //控制对应的元素移动
            div.style.left = targetX + "px"
            div.style.top = targetY + "px"
        }
        //4.在按下事件里面添加弹起事件 取消俩个事件
        document.onmouseup = function(){
            document.onmousemove =  document.onmouseup  = false
        }
    }

</script>

区间拖拽

1.给元素添加按下事件 (获取元素的父盒子的位置 在网页上的位置 获取对应的鼠标在元素里面的位置)

2.在按下事件里面添加移动事件(父元素添加) (获取当前鼠标在父盒子里面的位置 - 对应的鼠标在元素的位置 设置对应的位置 )

3.在弹起事件里面取消对应的移动事件以及弹起事件

<div class="box">
    <div class="moveBox"></div>
</div>
<script>
    //1.获取元素 大盒子和移动的盒子
    var box = document.querySelector(".box")
    var moveBox = document.querySelector(".moveBox")
    //2.给小盒子加鼠标按下事件 记录对应的鼠标在小盒子的位置 记录大盒子的位置
    //鼠标在大盒子里面的位置其实就是 当前的鼠标在页面上的位置(page) - 大盒子离页面的距离(offset家族)
    //当前的鼠标在页面上的位置(pageX) - 大盒子离页面的距离(offsetLeft)
    //当前的鼠标在页面上的位置(pageY) - 大盒子离页面的距离(offsetTop)
    moveBox.onmousedown =  function(e){
        e = e || window.event
        var currentX = e.offsetX //鼠标在小盒子里面的位置
        var currentY = e.offsetY
        //3.按下事件里面给大盒子添加移动事件 
        //(得到鼠标在大盒子里面的位置 - 鼠标在小盒子里面的位置 控制对应的移动)
        box.onmousemove = function(e){
            e = e || window.event
            // var targetX = e.offsetX - currentX
            // var targetY = e.offsetY - currentY
            var targetX = e.pageX - this.offsetLeft - currentX
            var targetY = e.pageY - this.offsetTop - currentY
            //最大的移动区间就是 父元素的宽度-子元素的宽度
            var maxX = this.offsetWidth - moveBox.offsetWidth
            var maxY = this.offsetHeight - moveBox.offsetHeight
            //边界判断
            // 如果当前定位的位置小于0就让他等于0
            if(targetX<0){
                targetX = 0
            }
            if(targetY<0){
                targetY = 0
            }
            //如果当前移动的距离大于我们最大的距离就让他等于这个距离
            if(targetX>maxX){
                targetX = maxX
            }
            if(targetY>maxY){
                targetY = maxY
            }
            //控制小盒子的位置
            moveBox.style.left = targetX + "px"
            moveBox.style.top = targetY + "px"
        }
        //4.取消对应的大盒子的移动事件 以及大盒子的弹起事件
        box.onmouseup = function(){
            box.onmouseup = box.onmousemove = false
        }
    }

</script>
公式
  • 鼠标在大盒子里面的位置其实就是 = 当前的鼠标在页面上的位置(page) - 大盒子离页面的距离(offset家族)
  • 移动的位置 = 得到鼠标在大盒子里面的位置 - 鼠标在小盒子里面的位置
  • 最大的移动区间 = 父元素的宽(高)度 - 子元素的宽(高)度

offset家族

offset家族是获取对应的偏移的位置 他有奶便是娘 (他的父元素谁加了定位他就基于谁 否则基于body)

offsetParent 偏移的父元素(选择离他最近加了定位的父元素)

offsetLeft 左偏移

offsetTop 上偏移

offsetWidth 偏移元素的宽度

offsetHeight 偏移元素的高度

获取样式

style属性 只能获取标签内容style属性里面存在的一些样式

如果需要获取对应的全局所有地方设置样式,将采取以下方法:

window.getComputedStyle() *

element.currentStyle (兼容ie8以下的浏览器)

//获取样式 获取所有的地方的样式 给定都是默认值 使用window对象
console.log(window.getComputedStyle($("h1")).backgroundImage);//返回的是一个样式对象 里面包含所有的样式
// 兼容ie 都是属性 直译 元素对象
console.log($("h1").currentStyle);
// 兼容写法 获取样式对象
function getStyle(element){
    return window.getComputedStyle?window.getComputedStyle(element):element.currentStyle
}

事件监听器

1.采用了观察者模式(observer)

2.同一个事件可以有多个处理函数

3.在添加事件的时候对应的处理函数不能是匿名函数(不然是不能被移除的)

添加事件监听 addEventListener

addEventListener(监听事件名,处理函数,冒泡false 还是捕获 true)

移除事件监听 removeEventListener

removeEventListener(事件名,处理函数)

var btn =  document.querySelector("button")
function hanlder(){
    console.log("123");
}
//添加监听 同一个事件可以有多个处理函数
btn.addEventListener('click',hanlder,false)
btn.addEventListener('click',function(){
    console.log("456");
},false) //是否捕获
//移除事件监听 函数的指向不一样 开辟俩个内存空间 地址是不一样 移除不了
//移除对应的事件名中某个匹配处理函数
btn.removeEventListener('click',hanlder)
//兼容 ie8以下
// btn.attachEvent("onclick",fn) 添加
// btn.detachEvent("onclick",fn) 移除
封装的兼容方法
//事件监听器的兼容
//添加事件的元素 事件类型 处理函数
function addEvent(element,type,fn){
    element.addEventListener?element.addEventListener(type,fn):element.attachEvent(`on${type}`,fn)
}
function removeEvent(element,type,fn){
    element.removeEventListener?element.removeEventListener(type,fn):element.detachEvent(`on${type}`,fn)
}
posted @ 2022-08-08 21:34  CHENNGE  阅读(110)  评论(0)    收藏  举报