JS事件

202 阅读8分钟

事件的概念

日常生活中事件: 发生并得到处理的操作(即事情来了, 然后处理)
在JS中的事件是: 用户在页面上操作, 然后我们要调用函数来处理。 js属于事件驱动编程。

事件的模式

JavaScript有两种事件实现模式: 内联模式脚本模式

1.内联模式

直接在HTML标签中添加事件。这种模型是最传统简单的一种处理事件的方法。但是这种模式中事件和HTML是混写的,并没有将JS与HTML分离,当代码量多了以后,对后期代码维护和扩展很不利。

<body>
    <button onclick="fn('内联模式')">点击</button>
    <script>
        //内联模式
        //  fn必须是全局函数
        function fn(str){
            console.log(str);//控制台打印:内联模式
        }
    </script>
</body>

【注】内联模式调用的函数不能放到window.onload里面, 否则会找不到该函数

2.脚本模式

脚本模式能将JS代码和HTML代码分离,符合代码规范。

<body>
    <button>点击</button>
    <script>
        //脚本模式
        //【注】当一个元素上绑定了内联与脚本,脚本模式优先
    </script>
    <script src="js/03.index.js"></script>
</body>

03.index.js

var btn=document.querySelector("button")
btn.onclick=function(){
    console.log("脚本模式");
}

事件的分类

1.鼠标事件

<body>
    <div class="box">
        <div class="box2"></div>
    </div>
</body>
.box{
    width: 200px;
    height: 200px;
    background-color: green;
    display: flex;
    justify-content: center;
    align-items: center;
}
.box2{
    width: 80px;
    height: 80px;
    background-color: pink;
}

onclick

单击鼠标按钮并在松开时触发

var box=document.querySelector(".box");

box.onclick=function(){
    console.log("onclick 鼠标单击");
}

ondblclick

双击鼠标按钮时触发

var box=document.querySelector(".box");

box.ondblclick=function(){
    console.log("ondblclick 鼠标双击");
}

onmousedown

按下了鼠标未松开时触发

var box=document.querySelector(".box");

box.onmousedown=function(){ 
    console.log("onmousedown 鼠标按下");
}

onmouseup

释放鼠标按钮时触发

var box=document.querySelector(".box");

box.onmouseup=function(){
    console.log("onmouseup 鼠标抬起");
}

onmouseenter

当鼠标移入某个元素的那一刻触发

var box=document.querySelector(".box");

box.onmouseenter=function(){
    console.log("onmouseenter 鼠标移入");
}

onmouseleave

当鼠标刚移出某个元素的那一刻触发

var box=document.querySelector(".box");

box.onmouseleave=function(){
    console.log("onmouseleave 鼠标移出");
}

onmouseover

当鼠标移入某个元素的那一刻触发

var box=document.querySelector(".box");

box.onmouseover=function(){
    console.log("onmouseover 鼠标移入");
}

onmouseout

当鼠标刚移出某个元素的那一刻触发

var box=document.querySelector(".box");

 box.onmouseout=function(){
    console.log("onmouseout 鼠标移出");
}

mouseover/mouseout和mouseenter/mouseleave的区别是:
区别一:
mouseover/mouseout: 元素的子元素移入/移出也会触发事件
mouseenter/mouseleave: 元素的子元素移入/移出不会触发事件
区别二:
代码中同时存在时
mouseover 优先于 mouseenter
mouseout 优先于 mouseleave

onmousemove

当鼠标指针在某个元素上移动时触发

var box=document.querySelector(".box");

box.onmousemove=function(){
    console.log("onmousemove 鼠标移动");
}

onmousewheel

当鼠标在某个元素上滚轮滚动时触发

var box=document.querySelector(".box");

box.onmousewheel=function(){
    console.log("onmousewheel 鼠标移入滚轮滚动");
}

2.键盘事件

<input type="text">

onkeydown

当用户按下键盘上某个键触发,如果按住不放,会重复触发

var txt=document.querySelector("input");

txt.onkeydown=function(){
    console.log(this.value);
}

onkeyUp

当用户释放键盘上的某个键触发

var txt=document.querySelector("input");

txt.onkeyup=function(){
    console.log(this.value);
}

onkeypress

当用户按下键盘上的字符键触发,如果按住不放,会重复触发

var txt=document.querySelector("input");

txt.onkeypress=function(){
    console.log(this.value);
}

3.html事件

onload

1)dom结构加载完成,并且外部所有的资源加载完成才触发。
2)凡是带有src属性的标签都有一个onload事件(img,script...)

window.onload = function () {
    console.log("页面加载完成");
}

unonload

当页面完全卸载后触发。关闭浏览器会触发一次,刷新页面也会触发一次。

window.onunload = function () {
    console.log("卸载事件……");
}

onresize

页面大小发生改变的时候就会触发。

 //改变窗口大小的时候才会触发,刷新不会自动触发
window.onresize=function(){
    var w=document.documentElement.clientWidth;
    if(w>0&&w<360){
        document.body.style.backgroundColor="green"
    }else if(w>=360&&w<780){
        document.body.style.backgroundColor="yellow"
    }else if(w>=780&&w<960){
        document.body.style.backgroundColor="red"
    }else{
        document.body.style.backgroundColor="pink"
    }
}
//事件触发 注意要先绑定函数,再触发事件
window.onresize()

onwheel

在页面中滚动滚动条时触发,不一定要有滚动条元素。

document.onwheel=function(){
    console.log("onwheel");
}

onscroll

当用户滚动带滚动条的元素时触发。

document.onscroll=function(){
    console.log("onscroll");
}

oninput

用户在输入立即触发

document.onscroll=function(){
    console.log("onscroll");
}

onchange

内容改变失去焦点后触发。

var userName=document.querySelector("#username")
userName.onchange=function(){
    console.log(this.value);
}

oninput和onchange的区别

  1. oninput 事件在元素值发生变化是立即触发,而onchange是在元素失去焦点时触发。
  2. 另外一点不同是 onchange 事件也可以作用于 <keygen> 和 <select> 元素。

onselect

当用户选择文本框(input 或 textarea)中的内容触发。

var userName=document.querySelector("#username")
userName.onselect=function(){
    console.log(this.value);
}

onblur

当页面或元素失去焦点时触发。

var userName=document.querySelector("#username")
userName.onblur=function(){
    console.log(this.value);

onfocus

当页面或者元素获得焦点时触发。

var userName=document.querySelector("#username")
userName.onfocus=function(){
    console.log(this.value);
}

onsubmit

当用户点击提交按钮在<form>元素节点上触发。

//获取表单对象
var myForm=document.forms[0];

myForm.onsubmit=function(){
    return false;
    //false 阻止表单的默认行为,不让表单提交  
    //true 会触发html的表单提交行为
}

onreset

当用户点击重置按钮在<form>元素节点上触发。

//获取表单对象
var myForm=document.forms[0];

myForm.onreset=function(){
    return true;
}

oncontextmenu

当用户右击鼠标时触发并打开上下文菜单

document.oncontextmenu=function(e){
    console.log("右击鼠标时打开上下文菜单");
}

事件对象(event对象)

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

获取事件对象

通过给函数添加一个参数获取事件对象

var box=document.querySelector(".box")
box.onclick=function(evt){
    //ie6+ window.event
    // console.log(window.event);
    //google 
    // console.log(evt);
    //兼容写法
    var e=evt||window.event
    console.log(e);
}

事件对象的属性

button

鼠标按下了哪个键 image.png

window.onmousedown=function(evt){
    var e=evt||window.event;
    console.log(e.button);//0左键点击 1滚轮点击 2右键点击
}

type

事件类型

var box = document.querySelector(".box")
box.onclick = function (evt) {
    var e = evt || window.event;
    console.log(e.type);//click
}

target 和 srcElement

目标对象,存放绑定事件的元素节点对象

var box = document.querySelector(".box")
box.onclick = function (evt) {
    var e = evt || window.event;
    console.log(e.target);//<div class="box"> </div>
    console.log(e.srcElement);//<div class="box"> </div>
    //e.target: Ie9+ 火狐、谷歌;
    //e.srcElement:ie 678;
}

charCode

字符按键的字符编码

//charCode只能在onkeypress事件中生效在onkeydown中没有作用
window.onkeypress=function(evt){
    var e=evt||window.event
    console.log(e.charCode);
}

keyCode

按键的字符编码

window.onkeydown=function(evt){
    var e=evt||window.event
    console.log(e.keyCode);
}

key

按键的字符

window.onkeydown=function(evt){
    var e=evt||window.event
    console.log(e.key);
}

altKey

按下alt键返回true,否则返回false

window.onkeydown=function(evt){
    var e=evt||window.event
    console.log(e.altKey);
}

shiftKey

按下shift键返回true,否则返回false

window.onkeydown=function(evt){
    var e=evt||window.event
    console.log(e.shiftKey);
}

ctrlKey

按下ctrl键返回true,否则返回false

window.onkeydown=function(evt){
    var e=evt||window.event
    console.log(e.ctrlKey);
}

metaKey

按下win键返回true,否则返回false

window.onkeydown=function(evt){
    var e=evt||window.event
    console.log(e.mateKey);
}

clientX , clientY

浏览器可视区域的x坐标,以及浏览器可视区域的y坐标

var box = document.querySelector(".box")
box.onclick = function (evt) {
    var e = evt || window.event;
    console.log(e.clientX, e.clientY);//点击的位置到浏览器的左上角的x轴和y轴距离
}

pageX , pageY

浏览器内容区域的x坐标,以及浏览器内容区域的y坐标

var box = document.querySelector(".box")
box.onclick = function (evt) {
    var e = evt || window.event;
    console.log(e.pageX, e.pageY);//点击的位置到内容区域的左上角的x轴和y轴距离
}

screenX , screenY

显示器屏幕的x坐标,以及显示器屏幕的y坐标

var box = document.querySelector(".box")
box.onclick = function (evt) {
    var e = evt || window.event;
    console.log(e.screenX, e.screenY);//点击的位置到屏幕的左上角的x轴和y轴距离
}

offsetX , offsetY

鼠标点击的元素位置距离元素左边界的x坐标及y坐标

var box = document.querySelector(".box")
box.onclick = function (evt) {
    var e = evt || window.event;
    console.log(e.offsetX, e.offsetY);
}

stopPropagation() 和 cancelbubble=true

作用:停止冒泡

div{
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%,-50%);
}
.box1{
    width: 500px;
    height: 500px;
    background: yellowgreen;
    .box2{
        width: 350px;
        height: 350px;
        background-color: skyblue;
        .box3{
            width: 200px;
            height: 200px;
            background-color: pink;
        }
    }
}
<div class="box1">box1
    <div class="box2">box2
        <div class="box3">box3</div>
    </div>
</div>

1.没有停止冒泡时,事件会从内往外传递:

var box1=document.querySelector(".box1")
var box2=document.querySelector(".box2")
var box3=document.querySelector(".box3")
box3.onclick=function(){
    console.log("box3");
}
box2.onclick=function(){
    console.log("box2");
}
box1.onclick=function(){
    console.log("box1");
}
document.body.onclick=function(){
    console.log("body");
}
document.onclick=function(){
    console.log("document");
}
window.onclick=function(){
    console.log("window");
}

点击box3元素,运行结果:

image.png 2.停止冒泡:

box3.onclick=function(evt){
    console.log("box3");
    var e=evt||window.event;
    //停止冒泡
    // e.cancelBubble=true;//ie 了解即可
    e.stopPropagation(); //重点
    //兼容写法 了解即可
    // if(e.cancelBubble){
    //     e.cancelBubble=true;
    // }else{
    //     e.stopPropagation();
    // }
}

点击box3元素,运行结果: image.png

preventDefault() 和 returnValue=false

作用:阻止默认行为

可阻止的默认行为:

  1. 表单,提交,重置的行为
  2. a标签,跳转的行为
  3. 图片 拖拽的行为
  4. 右击菜单,显示菜单行为
    ...
<body>
    <!-- 默认会跳转到百度页面 -->
    <a href="http://www.baidu.com">跳转</a>
    <script>
        var oA=document.querySelector("a");
        oA.onclick=function(evt){
            //阻止默认行为  让a链接无法跳转到百度页面
            // 方式1  重点
            // return false;
            
            var e=evt||window.event;
            
            //方式2 ie 了解
            // e.returnValue=false
            
            //方式3  重点
            e.preventDefault()
            
            //方式4 兼容写法 了解
            // if(e.preventDefault){
            //     e.preventDefault()
            // }else{
            //     e.returnValue=false
            // }
        }
    </script>
</body>

事件流

事件流是描述的从页面接受事件的顺序,当几个都具有事件的元素层叠在一起的时候, 那么你点击其中一个元素,并不是只有当前被点击的元素会触发事件,而层叠在你点击范围的所有元素都会触发事件。事件流包括两种模式:冒泡捕获
事件冒泡从里往外逐个触发。事件捕获从外往里逐个触发。现代的浏览器默认情况下都是事件冒泡的模式。

事件监听

当我们需要对一个元素设置多种点击事件时,如果写两个onclick那么后写的会覆盖先写的那个。无法达到想要的效果,这时就可以设置事件监听。

var box=document.querySelector(".box")
box.onclick=function(){
    console.log("1111");
}
//还想添加一个点击事件,直接写
// box.onclick=function(){//这样的话后写的会覆盖先写的
//     console.log("2222");
// }

//可以添加事件监听
//addEventListener("事件类型",函数,true/false)
//addEventListener("事件类型",函数,{once:true,capture:true})
// capture 捕获
// once 1次
box.addEventListener("click",function(){//这样就不会被覆盖了
    console.log("2222");
})

绑定与移除事件监听

addEventListener()添加事件监听,有三个参数:事件类型、要执行的回调函数、和一个可选的布尔值参数,用于指定事件是否在捕获阶段触发(默认为false表示冒泡,true表示捕获)。
removeEventListener()移除事件监听,有三个参数:要移除的事件类型、要移除的事件监听函数、和一个布尔值参数(与要移除的事件监听一致)。

<body>
    <button>绑定事件</button>
    <button>移除事件</button>
    <div class="box"></div>
    <script>
        //addEventListener 添加事件监听
        //removeEventListener 移除事件监听
        var btns=document.querySelectorAll("button");
        var box=document.querySelector(".box")
        box.onclick=function(){
            console.log("1111");
        }
        btns[0].onclick=function(){
            //绑定多个事件监听
            box.addEventListener("click",fn1)
            box.addEventListener("click",fn2)
        }
        function fn1(){
            console.log("2222");
        }
        function fn2(){
            console.log("3333");
        }
        //移除监听事件   
        btns[1].onclick=function(){
            box.removeEventListener("click",fn1)
        }
    </script>
</body>