JavaScript中的event讲解及一些常见案例

        JavaScript中的event就是发生在dom元素上的事件,你也许已经使用过不少dom事件,但是event对象在js中有很多强大并且常用的功能。本文将讲解部分常用event的属性方法。

目录

event.target 和 event.currentTarget

事件冒泡和事件捕捉 e.stopPropogation()

阻止默认事件 event.preventDefault()

案例1. 表单提交

案例2. 自定义右键菜单

event.target 和 event.currentTarget

        event最常用的属性之一就是他的targetcurrentTarget属性。event.target指向事件发生的元素对象,而currentTarget指向事件被绑定的对象。你可能会觉得,这两句话看起来好像看起来没什么区别,那我们就用下面这个例子来阐述一下实际的效果。


        首先,我们有一组按钮在一个容器里面(带有浅色背景颜色的是容器本身)

    <div class="container" name="container">
        <button class="btn" name="button1" id="button1">click</button>
        <button class="btn" name="button2" id="button2">click</button>
        <button class="btn" name="button3" id="button3">click</button>
        <button class="btn" name="button4" id="button4">click</button>
        <button class="btn" name="button5" id="button5">click</button>
        <button class="btn" name="button6" id="button6">click</button>
        <button class="btn" name="button7" id="button7">click</button>
        <button class="btn" name="button8" id="button8">click</button>
        <button class="btn" name="button9" id="button9">click</button>
    </div>

在JavaScript中,我们用querySelector选中container容器和他的所有子元素按钮,并且给container绑定一个点击事件,来打印event对象(下面我们用e来简写event):

        const btns = document.querySelectorAll('.btn')
        const container = document.querySelector('.container')

        container.addEventListener('click', (e) => {
            // console.log(e.target.getAttribute('name'))
            console.log(e.currentTarget)
            console.log(e.target)
        })

        我们每次点击container,container都会打印他的target和currentTarget。如果我们点击按钮之外的容器区域,那么e.target和e.currentTarget将都会是容器的dom元素。但如果我们点击的是其中一个按钮的话,那么e.target将会变成按钮的dom元素,并且e.currentTarget不变。

        这个结果正符合我们之前的描述:e.target的值并不是恒定的,他可以是事件绑定的对象,也可能是事件绑定对象的子元素。然而e.currentTarget一直都会指向事件绑定的对象。我们可以通过这个原理,获取每个按钮上name标签的值:

        container.addEventListener('click', (e) => {
            console.log(e.target.getAttribute('name')) // button[num]
            console.log(e.currentTarget.getAttribute('name')) // container
        })

        除了特殊属性需要之外,我们还可以直接获取事件dom目标的classstyleid等属性

        container.addEventListener('click', (e) => {
            
            // 给点击的元素添加class名 ’button‘
            e.target.classList.add('button')

            // 改变点击的元素的文字颜色
            e.target.style.color = 'red'

            // 获取点击的元素的id值
            console.log(e.target.id)
        })

事件冒泡和事件捕捉 e.stopPropogation()

        事件冒泡在JavaScript中指的是当一个元素在另一个事件里面的时候,当你触发里面的元素的事件时,如果外面的元素也绑定了相同类型的事件,那么外面元素的事件也会被触发。

        我们仍然可以使用上一个例子来阐述其中的效果。此时,不只是container有一个事件绑定,我们给每一个按钮自身也绑定一个事件: 

        btns.forEach(btn => {
            btn.addEventListener('click', e => {
                console.log('你点击了一个按钮')
            })
        })

        那么,当你点击任何一个按钮的时候,你不光会触发按钮自身的事件,还会触发container的事件;因为container是button的外围元素,并且他和按钮都绑定了相同类型的点击事件。当一个事件发生在一个元素上,它会首先运行在该元素上的处理程序,然后运行其父元素上的处理程序,然后一直向上到其他祖先上的处理程序。这就叫事件冒泡

        事件冒泡的好处是可以减少事件的绑定数量。但同时,很多时候你不想让事件冒泡。比如,我们就只想在点击按钮的时候触发按钮的事件,而不触发container的点击的话,我们可以调用按钮的event的一个方法,叫做stopPropogation().

        btns.forEach(btn => {
            btn.addEventListener('click', e => {
                e.stopPropogation()
                console.log('你点击了一个按钮')
            })
        })

阻止默认事件 event.preventDefault()

        最常见的默认事件的包括表单上传,鼠标右键打开浏览器菜单, checkbox不允许选择,a标签不会转换页面等等。这里我们用表单和鼠标右键的例子来表明它的作用。

案例1. 表单提交:

    <form method="post" onsubmit="submitForm(event)">
        <input type="text">
        <input type="text">
        <input type="text">
        <input type="text">
        <input type="submit" value="提交表单">
    </form>

        function submitForm(e) {
            console.log(e)
            e.preventDefault()
        }

        首先,很多同学容易误解的是,尽管你提交表单的时候的确点击了提交按钮,但是你需要把事件绑定在表单上而不是提交按钮上,因为按钮实际上触发的是表单的submit提交事件。

        表单的默认行为是将表单数据上传到某个网址,也就是form上的action属性的内容。即使你不写action,在提交表单时也会默认刷新页面。但这大部分时候并不是我们想要的,或者至少我们想对表单的行为有更多的控制。这时候,我们就要通过event.preventDefault()来阻止表单刷新页面。

        然后,我们就可以自己决定表单提交后的行为,比如我们想发送一个patch请求到某个网址上:(如果你对promise的链式写法不了解,可以先看看promise的基本用法

        function submitForm(e) {
            console.log(e)
            e.preventDefault()
            fetch('url', {
                method: 'PATCH',
                data: {
                    /* something */
                },
                headers: {
                    /* something */
                }
            }).then(response => console.log(response))
            .catch(error => console.log(error))
        }

案例2. 自定义右键菜单:

        我们右键在浏览器点击的时候,浏览器会弹出一个选项栏,我们可以通过这个方式刷新页面或者打开控制台等等。但有时候,我们想让浏览器弹出一个我们自定义的选择框,这时候我们也需要禁止浏览器的默认行为。

        首先,我们先总结一下我们的需求:

        1. 右键点击container时,弹出自定义选项栏

        2. 不管在哪里点击,选项栏都会出现在鼠标旁边,就像默认选项栏一样

        3. 左键点击选项内容或者选项栏之外时,关闭选项栏

 

        在了解需求后,我们先简单构建一下样式:

    <style>
        .menu{
            display: flex;
            flex-flow: column wrap;
            box-shadow: 0 0 6px #666;
            width: 200px;
            border-radius: 8px;
            position: fixed; 菜单始终出现在页面中,并且可以受left和top的属性操作
            top: 0px;
            left: 0px;
            background-color: white;
            opacity: 0; 默认隐藏菜单
        }
        
        .menu span{
            height: 30px;
            line-height: 30px;
            font-size: 16px;
            padding: 8px 20px;
            cursor: pointer;
        }
    </style>

    <div class="container">

    </div>

    <div class="menu">
        <span class="option">详情</span>
        <span class="option">修改</span>
        <span class="option">删除</span>
    </div>

        接下来,利用contextmenu事件,也就是打开菜单的事件,来显示自定义菜单,并且阻止他的默认行为。

        function openMenu(e) {
            e.preventDefault();
            menu.style.opacity = 1
        }

        container.addEventListener('contextmenu', e => {
            openMenu(e)
        })

        目前为止,菜单只会出现在他默认的位置,event对象里还有很多有用的属性,比如我们这里需要用到的clientXclientY,他们会反应一个位置在当前窗口中的坐标值。我们正需要他们来帮我确定菜单的位置。

        function openMenu(e) {
            e.preventDefault();

            // 得到当前鼠标的坐标
            console.log(e.clientY, e.clientX)

            menu.style.opacity = 1

            // 利用当前坐标值,更改menu的top和left属性的值
            menu.style.top = e.clientY + 'px'
            menu.style.left = e.clientX + 'px'
        }

         最后,当我们点击菜单外的container或者菜单选项的时候,我们想要关闭菜单:

        const options = document.querySelectorAll('.option')      

        options.forEach(option => {
            option.addEventListener('click', () => {
                menu.style.opacity = 0
            })
        })

        container.addEventListener('click', (e) => {
            menu.style.opacity = 0
        })

 总结:

        JavaScript中的event对象里还包含很多对我们可能有用的信息,比如screenX,screenY,事件类型等等,但文中提及的几个是最常见的,尤其是事件冒泡,事件对象,事件默认行为,需要熟练掌握

猜你喜欢

转载自blog.csdn.net/a1611107035/article/details/127729121