JavaScript - Day11、12 - 事件

一、事件复习

事件三要素: 事件源 + 事件名称 + 事件处理程序

    事件源:谁触发这个事件(按钮btn)

    事件名称:触发了什么事件(点击click事件)

    事件处理程序:事件触发后要执行的代码(函数形式)--- 可以是有名字的函数,不加小括号

1.事件语法:标签.on事件类型 = 函数

二.事件类型

   1.鼠标事件

       (1)click:左键单击

       (2)contextmenu:右键单击

       (3)dblclick:双击

       (4)mousedown:左键按下

       (5)mouseup:左键弹起

       (6)mouseover:鼠标放上去(在子元素上也会触发)

       (7)mouseout:鼠标离开

       (8)mouseenter:鼠标放上去

       (9)mouseleave:鼠标离开

       (10)mousemove:鼠标移动事件

       (11)mousewheel:鼠标滚轮事件

   2.浏览器事件

       (1)load:加载

       (2)scroll:滚动

       (3)resize:大小改变

   3.键盘事件

       (1)keydown:按下

       (2)keyup:弹起

       (3)keypress:敲打

   4.表单事件

       (1)submit:提交表单 - 给form标签绑定,点击表单域中提交按钮的时候触发,在跳转之前触发

       (2)focus:获取焦点

       (3)blur:失去焦点

       (4)change:内容改变并失去焦点 - 下拉框选项/单选框状态/复选框状态改变

       (5)input:input的value值改变 - 改变了文本框的内容就会触发的事件

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

<body>
    <form action="">
        <input type="radio" name="gender" value="男">男
        <input type="radio" name="gender" value="女">女
        <br>
        <input type="checkbox" name="hobby" value="唱歌">唱歌
        <input type="checkbox" name="hobby" value="跳舞">跳舞
        <input type="checkbox" name="hobby" value="摇头">摇头
        <input type="checkbox" name="hobby" value="rap">rap
        <br>
        <input type="text" name="username">
    </form>
</body>
<script>
    // change
    var radioInput = document.querySelector('[name="gender"]')
    // 当用户点击了这个单选框并让他的状态发生了改变触发事件
    radioInput.onchange = function () {
        console.log(radioInput.checked);
        console.log('改变了');
    }

    // // 点击选中,再点击取消
    var flag = false
    radioInput.onclick = function () {
        // 获取当前input的选中状态
        // console.dir(radioInput) // 第一种写法获取当前input的选中状态
        // console.log(radioInput.checked); // 第二种写法获取当前input的选中状态
        // 如果他的状态是true
        // if (!radioInput.checked) {
        //     radioInput.checked = true
        // }
        if (flag) {
            // 设置选中状态
            radioInput.checked = false
            flag = false
        } else {
            radioInput.checked = true
            flag = true
        }
    }

    var checkboxInput = document.querySelector('[name="hobby"]')
    checkboxInput.onchange = function () {
        console.log(checkboxInput.checked);
        console.log('改变了');
    }


    // input - 百度就是这个写法
    var textInput = document.querySelector('[name="username"]')
    textInput.oninput = function () {
        console.log(textInput.value);
    }
</script>

三、事件流

1.定义

       每个事件发生的时候,都会有一个触发并执行的过程,也就是事件的传播过程,我们称之为事件流。简单来说,事件从开始触发到执行结束所经历的整个过程.

2.事件流包含3个阶段

   (1)捕获阶段:由外向内找目标元素的过程

   (2)目标阶段:开始执行目标元素事件函数

   (3)冒泡阶段:由内向外离开目标元素的过程

     事件捕获阶段:事件开始由顶层元素触发,然后逐级向下传播,直到目标元素,依次执行其身上绑定的事件。

     事件目标阶段(处理阶段):触发当前自身的事件。

     事件冒泡阶段:事件由目标元素先接收,然后逐级向上传播,达到最顶层元素,依次执行其身上绑定的事件。

3.注意

 (1)目标元素的事件在目标阶段执行,其他事件会在冒泡阶段执行

 (2)目标元素的祖宗标签如果有同类型的事件,会在冒泡阶段执行

四、事件侦听器

1.定义:另外一种事件绑定方式 - 事件侦听器

2.语法:标签.addEventListener(事件类型, 函数代码, 当前事件是否在别人的捕获阶段执行,默认是false)

    // 事件流
    var small = document.querySelector('.small')
    var middle = document.querySelector('.middle')
    var big = document.querySelector('.big')
    small.addEventListener('click', function () {
        console.log('小');
    })

    middle.addEventListener('click', function () {
        console.log('中');
    }, true)

    big.addEventListener('click', function () {
        console.log('大');
    })

    // 同类型事件不能绑定多次
    small.onclick = function(){
        console.log('111');
    }
    small.onclick = function(){
        console.log('222');
    } // 覆盖第一个111

    // 使用事件侦听器 - 同类型事件可以绑定多次
    small.addEventListener('click',function(){
        console.log('111');
    })
    small.addEventListener('click',function(){
        console.log('222')
    })

三、事件解绑

1.定义

     (1)什么叫解绑:把事件删除掉

     (2)为什么解绑:有的事件执行一次后就不需要执行,但是事件会一直保存在内存中,浪费内存

     (3)怎么解绑:

                   标签.on类型 = 函数  ----------  解绑方式:标签.on类型 = null

                   事件侦听器  ---------------------  解绑方式:标签.removeEventListener(事件类型, 绑定的那个函数)

2.事件绑定标签.on类型=函数 ,事件绑定后,存储的函数不会自动丢失,会一直在内存中保存下去。

<body>
    <button>按钮</button>
    <p style="background-color: #f00;">解绑</p>
</body>
<script>
    var btn = document.querySelector('button')
    btn.onclick = function () {
        console.log(666);
    }
    console.dir(btn)
</script>
// 事件为什么能触发?因为我们给标签的 onclick属性赋值了一个函数
// 为什么触发一次后还能触发?因为触发一次后 onclick属性的值还是一个函数
    var btn = document.querySelector('button')
    console.dir(btn)
// 事件绑定之前为什么不能触发?因为绑定之前 onclick属性 值是null

3.解绑 - 事件解绑

    btn.onclick这种绑定方式 - 解绑:btn.onclick = null

    var btn = document.querySelector('button')
    btn.onclick = function () {
        console.log(666);
        btn.onclick = null // 解绑,还原到被绑定之前
    }
    console.dir(btn)

4.事件侦听器绑定

    var btn = document.querySelector('button')
    btn.addEventListener('click', function () {
        console.log(666);
    })

5.事件侦听器解绑

         事件侦听器绑定的事件,解绑需要使用特殊的方式:

         标签.removeEventListener(事件类型, 绑定的那个函数)

    var a = function(){
            console.log(666); 
        }
    var b = function () {
        console.log(666);
    }
    console.log(a === b); /* false - 不相等 - 因为把一段函数赋值给变量a,function是引用
                  类型,把函数值存到堆里,把地址存到栈里,b同样也是,完全没关系,所以不相等 */



    var a = function(){
            console.log(666); 
        }
    var btn = document.querySelector('button')
    document.querySelector('p').onclick = function () {
        // 解绑btn的事件
        btn.removeEventListener('click', a)
    }

四、事件对象

 1.引入

document.querySelector('button').onclick = fn
function fn(a){
    conso.log(666)
}
/* 如上这样一个事件,想给这个函数传第一个实参,让形参a接收,怎么传? - 没找到函数调用的小
括号,但肯定调用了,但是在哪里调用的呢?因为事件绑定后,事件函数是由浏览器监听到用户触发
事件后,去调用这个函数执行的 */
// 浏览器在调用这个函数的时候,会给函数传递一个实参
// 这个实参是一个对象 - 事件对象:其中记录了很多跟当前事件相关的信息,比如鼠标的位置

2.定义

       浏览器为事件提供了一个对象,用来记录事件的各种具体信息,例如,鼠标点击的位置、鼠标按键的信息、键盘的键码。。。这就是事件对象。浏览器在调用事件函数的时候,给函数传递了一个实参 --- 对象

     (1)第一种写法:针对IE浏览器,基本都兼容

<body>
    <button id="btn">按钮</button>
</body>
<script type="text/javascript">
    btn.onclick = function () {
        console.log(window.event);
    }
</script>

     (2)第二种写法:针对W3C标准浏览器,在IE低版本浏览器中还不兼容

btn.onclick=function(e){
    console.log(e);
}

     (3)第三种写法:兼容所有浏览器的写法

btn.onclick = function(e){
    var ev = e || window.event
    console.log(ev);
}

如果是行内绑定的事件,就将事件对象当做参数传进来即可。且必须是event。

<button onclcik="fn(event)">
    按钮
</button>
<script>
    function fn(e){
        console.log(e);
    }
</script>

五、事件对象的作用

        储存了当前事件相关的所有信息

        怎么获取对象?

              事件函数通过形参接收或window.event

1.获取事件类型

        事件对象.type ---- 看是什么事件

var btn = document.querySelector('button')
btn.onclick = function(e) {
btn.onmouseover = function(e) {
    console.log(e.type);    // 事件类型 - e.type
}

2.获取鼠标按键码

        事件对象.button

            (1)左键 - 0

            (2)滚轮 - 1

            (3)右键 - 2

<button id="btn">按钮</button> 
<script type="text/javascript">
btn.onmousedown = function(e){
    var ev = e || window.event;
    var code = ev.button;
    if(code == 0){
       console.log("您点击的是左键");
    }else if(code == 1){
        console.log("您点击的滚轮");
    }else if(code == 2){
        console.log("您点击的是右键");
    }else{
        console.log("不知道你点击的是什么");
    }
}
</script>

3.获取键盘按键码

        单个 - 事件对象.keyCode

            (1)回车键:13

            (2)空格键:32

            (3)上下左右:38 40 37 39

            (4)数字:数字对应的阿斯克码

            (5)字母:大写字母的阿斯克码

<body>
    <button id="btn">按钮</button>
</body>
document.onkeyup = function(e) {
    var code = e.keyCode    // 按键码 - e.keyCode
    console.log(code);
    var word = String.fromCharCode(code).toLowerCase()    // 判断是否按的是c键
    if(word === 'c') {
        console.log('按的c');
    }

</script>

       组合键 - 布尔值

            (1)事件对象.ctrlKey:alt 键和别的键一起按下得到 true,否则得到 false

            (2)事件对象.shiftKey:shift 键和别的键一起按下得到 true,否则得到 false

            (3)事件对象.altKey:ctrl 键和别的键一起按下得到 true,否则得到 false

            (4)事件对象.metaKey:win键和别的键一起按下返回true,否则返回false

document.onkeyup = function(e) {
    var code = e.keyCode
        console.log(e.ctrlKey);
    if(word === 'c' && e.ctrlKey) {
        console.log('按住了ctrl+c'); // 判断是否按住了ctrl+c
    }
}

4.获取鼠标位置

       相对标签 - 从元素内部开始计算的坐标

            (1)事件对象.offsetX

            (2)事件对象.offsetY

       相对浏览器窗口

              使用说明:不管页面滚动到哪里,都是根据窗口来计算坐标。(不会随着滚动条的滚动而

                                                                                                                                         发生改变)

            (1)事件对象.clientX

            (2)事件对象.clientY

       相对整个网页

              使用说明:会随着滚动条的滚动而加大,横向坐标也是一样的

            (1)事件对象.pagex

            (2)事件对象.pageY

<body>
x轴:<span>0</span>
<br>
y轴:<span>0</span>
</body>
<script>
document.onmousemove = function(e) {
    var x = e.pageX
    var y = e.pageY
    document.querySelectorAll('span')[0].innerText = x
    document.querySelectorAll('span')[1].innerText = y
}
</script>

5.阻止事件冒泡 - 任选其一,现在都兼容

           在事件对象中,有一个方法用来阻止事件冒泡,这个方法叫做stopPropagation。

            (1)事件对象.stopPropagation()

            (2)事件对象.cancelBubble = true

            (3)兼容写法 

                             if(e.stopPropagation) {

                                        e.stopPropagation()

                               } else {

                                         e.cancelBubble = true

                                  }

<style>
.big{
    width: 300px;
    height: 300px;
    background-color: #f00;
}
.middle{
    width: 200px;
    height: 200px;
    background-color: #0f0;
}
.small{
    width: 100px;
    height: 100px;
    background-color: #00f;
}
</style>
<body>
<div class="big">
    <div class="middle">
        <div class="small"></div>
    </div>
</div>
</body>
<script>
var big = document.querySelector('.big')
var small = document.querySelector('.small')
var middle = document.querySelector('.middle')
big.onclick = function() {
    console.log('大');
}
middle.onclick = function() {
    console.log('中');
}
small.onclick = function(e) {
    var e = e || window.event 
    //第一种 - 阻止事件冒泡 - e.stopPropagation()
    // e.stopPropagation()  

    //第二种 - 低版本ie中 - e.cancelBubble = true
    // e.cancelBubble = true 

    //第三种 - 兼容写法
    if(e.stopPropagation) {
        e.stopPropagation()
    } else {
        e.cancelBubble = true
    }   
    console.log('小');
}
</script>

6.阻止默认行为

       有的标签天生就有行为,用不着绑定事件,比如<a>

            (1)事件对象.preventDefault() - 低版本ie中不兼容

            (2)事件对象.returnValue = false - 在ie中可以使用

            (3)在事件的底部加 return false ----- 通常会在事件函数的最下面写一行代码,就能阻止

                                                                                                                                           默认行为

            (4)有链接的标签,将连接改成:   javasccript:;  ---- 如:<a href="javascript:;">百度</a>

<body>
<a href="http://baidu.com">百度</a>
</body>
<script>
// 有的标签天生就有行为,用不着绑定事件,比如<a>
document.querySelector('a').onclick = function(e) {
    console.log('点击了a标签。不跳了'); 
    // console.log(b); /* 此处打开b会报错,事件对象阻止默认行为就怕报错,如果报
                                                 错,后续代码就 执行不了 */
    e.preventDefault() // 第二种
}

7.获取精准的目标元素

            (1)事件对象.target

            (2)事件委托

                         概念:子委托父处理他的事件,事件委托也叫事件代理(看站谁的角度),使用事件委托技术能避免对每个子节点添加事件监听,相反把事件监听委托给父元素即可,这样可提高绑定事件的性能。

                         原理:事件冒泡

                         好处:(1)减少绑定次数,提高性能

                                     (2)动态添加的子标签也能有事件

                         缺点:(1)li标签比较多的时候,性能特别差,毕竟使用for循环相当于绑定了多

                                                                                                                                                    次

                                     (2)当动态给li添加元素的时候,新元素没有事件绑定

                         注意:事件委托底层就是通过事件冒泡来完成的,先触发父元素的事件,在通过事件对象的target属性找到具体的目标元素,进而在处理目标元素要执行的业务逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值