JavaScript08-DOM操作事件01

JavaScript08-DOM操作事件01

1.事件对象

<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        #div01 {
            width: 300px;
            height: 100px;

            border: 1px solid black;
        }

        #div02 {
            width: 300px;
            height: 50px;

            margin-top: 10px;
            border: 1px solid black;
        }
    </style>

    <script>
        window.onload = function () {
            // 获取鼠标在div01中移动的坐标,然后再div02中显示。
            let div01 = document.getElementById('div01');
            let div02 = document.getElementById('div02');

            /**
             * 当事件的响应函数触发时,浏览器都会传递一个参数作为回调函数的实参。
             *      这个实参就是事件对象,事件对象存储了当前事件的相关信息。
             * @param event 事件对象
             */
            // 当鼠标在div01上移动时,触发onmousemove事件。
            div01.onmousemove = function (event) {
                let x = event.clientX;
                let y = event.clientY;

                div02.innerText = `x = ${x}, y = ${y}`;
            }
        }
    </script>
</head>
<body>

<div id="div01"></div>
<div id="div02"></div>
</body>
</html>

2.练习-div随鼠标移动

<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        body {
            height: 3000px;
        }
        #div01 {
            width: 100px;
            height: 100px;

            border: 1px solid black;
            background-color: red;
            /*position: fixed;*/
            position: absolute;
        }
    </style>
    <script>
        window.onload = function () {
            let div01 = document.getElementById('div01');
            
            // 需要给当前的DOM设置鼠标移动事件
            document.onmousemove = function (event) {
                let x = event.clientX;
                let y = event.clientY;

                // 需要div开启定位(position: absolute;),设置偏移量才有效。
                // div01.style.left = x + 'px';
                // div01.style.top = y + 'px';

                // 设置div01.style.left = x + 'px',当body有滚动条时,clientX获取的时当前粗窗口的x坐标,
                // 会出现div不在当前窗口显示的问题。
                // 解决办法 1 设置div的position: fixed;,让div的定位以当期窗口作为参照物。

                // 解决办法 2 使用pageX,获取鼠标在当前页(窗口)的x坐标。不过pageX这个属性还在试验中。
                // div01.style.left = event.pageX + 'px';
                // div01.style.top = event.pageY + 'px';

                // 解决办法 3 使用document.documentElement.scrollLeft获取滚动条移动的距离,
                // 滚动条移动的距离+鼠标在当前窗口的坐标=鼠标在当前页的坐标。
                div01.style.left = x + document.documentElement.scrollLeft + 'px';
                div01.style.top = y + document.documentElement.scrollTop + 'px';
            }
        }
    </script>
</head>
<body>

<div id="div01"></div>
</body>
</html>

3.事件的冒泡

<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        #div01 {
            width: 100px;
            height: 100px;

            border: 1px solid black;
            background-color: #99ff99;
        }
        #sp01 {
            background-color: orange;
        }
    </style>
    <script>
        // 冒泡是指事件的向上传导,当元素上的事件被触发时,其祖先元素上的相同事件也会被触发。
        // 1 冒泡的发生只和结构有关,和元素的位置无关。
        // 2 取消事件冒泡的两种方式。
        //      1) event.cancelBubble = true;
        //      2) event.stopPropagation();
        window.onload = function () {
            document.getElementById('sp01').onclick = function (event) {
                // 取消事件的冒泡,取消事件的冒泡后,当前事件不会冒泡给div01
                //event.cancelBubble = true;
                event.stopPropagation();
                alert('sp01');
            };

            document.getElementById('div01').onclick = function () {
                // 当前div的点击事件会冒泡给document
                alert('div01');
            };

            document.onclick = function () {
                alert('document');
            }
        }
    </script>
</head>
<body>

<div id="div01">
    我是div01
    <div id="sp01">我是span</div>
</div>
</body>
</html>

4.事件的绑定

<html lang="en">
<head>
    <meta charset="UTF-8">
    <script>
        window.onload = function () {
            let btn01 = document.getElementById('btn01');
            // 1 给btn01绑定单击事件。
            // 通过给onclick属性设置值的方式绑定事件,只能绑定一个事件,
            // 如果绑定多个事件,则前面的事件被覆盖,所以在开发中不经常使用。
            btn01.onclick = function () {
                alert('btn01 A01');
            };

            btn01.onclick = function () {
                alert('btn01 A02');
            };

            // 2 通过addEventListener()添加事件,如果添加了多个事件,则多个事件都会触发。
            // addEventListener() 有三个参数。
            //      1 绑定的事件。如click,不需要on。
            //      2 事件触发执行的函数。
            //      3 是否进行事件的捕获,默认false,所以发生的是事件的冒泡;true,会发生事件的捕获,捕获时不会发生事件的冒泡。
            let btn02 = document.getElementById('btn02');
            function client01() {
                alert('btn02 A01');
            }

            // 通过addEventListener()添加事件。
            btn02.addEventListener('click', client01);

            function client02() {
                alert('btn02 A02');
            }
            btn02.addEventListener('click', client02);

            // 通过addEventListener() 绑定的事件如果需要删除,则需要使用removeEventListener()函数。
            btn02.removeEventListener('click', client02);
        }
    </script>
</head>
<body>

<button id="btn01">btn01</button>
<button id="btn02">btn02</button>
</body>
</html>

5.事件的捕获

<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        #div01 {
            width: 300px;
            height: 300px;

            background-color: #99ff99;
        }

        #div02 {
            width: 200px;
            height: 200px;

            background-color: red;
        }

        #div03 {
            width: 100px;
            height: 100px;

            background-color: orange;
        }
    </style>

    <script>
        window.onload = function () {
            // 关于事件的传播微软和网景有不同的理解。
            // 微软:事件应该由内向外传播,即先触发后代元素的事件,然后触发祖先元素的事件,事件的冒泡。
            // 网景,事件应该由外向内传播,即先触发祖先元素的事件,然后触发后代元素的时间,事件的捕获。

            // W3C将这两种理念进行整合,将事件分为三个阶段。
            //      1 事件的捕获。从最外层元素(window)向目标元素进行事件的捕获。
            //      2 目标元素。事件捕获到目标元素,捕获停止。
            //      3 事件的冒泡。从目标元素开始向最外层元素进行事件的传导。

            // 默认情况下,事件是在冒泡阶段开始触发的。事件传播行为只能是事件的捕获和事件的冒泡中的一个。
            let div01 = document.getElementById('div01');
            let div02 = document.getElementById('div02');
            let div03 = document.getElementById('div03');

            // addEventListener() 的第三个参数,是否进行事件的捕获,默认false,所以发生的是事件的冒泡。
            // true,会发生事件的捕获,不会发生事件的冒泡。
            div01.addEventListener('click', function () {
                alert('div01');
            }, true);

            div02.addEventListener('click', function () {
                alert('div02');
            }, true);

            div03.addEventListener('click', function () {
                alert('div03');
            }, true);

            let a01 = document.getElementById('a01');
            // 通过addEventListener()添加事件不能通过return false;来取消事件的默认行为。
            // addEventListener()事件的事件,可以通过preventDefault()来取消事件的默认行为。
            a01.addEventListener('click', function (event) {
                alert('123');

                // 取消事件的默认行为。
                event.preventDefault();
                return false;
            });
        }
    </script>
</head>
<body>

<div id="div01">
    <div id="div02">
        <div id="div03">

        </div>
    </div>
</div>

<a href="https://www.baidu.com" id="a01">去百度</a>
</body>
</html>

6.练习-div随鼠标移动,解决div移动到其他div下的问题

<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        #div01 {
            width: 100px;
            height: 100px;

            border: 1px solid black;
            background-color: orange;
            position: absolute;
        }

        #div02 {
            width: 100px;
            height: 100px;

            margin-left: 500px;
            margin-top: 100px;
            border: 1px solid black;
            background-color: black;
            position: absolute;
        }
    </style>

    <script>
        window.onload = function () {
            let div01 = document.getElementById('div01');

            // 给div绑定鼠标按下去的事件,鼠标按下去之后修改div的坐标。
            div01.onmousedown = function () {

                // 计算鼠标相对于div的左偏移量,相当于获取鼠标在div中的坐标。
                let x = event.clientX - div01.offsetLeft;
                // 计算鼠标相对于div的上偏移量
                let y = event.clientY - div01.offsetTop;

                // 通过document的鼠标移动事件修改div的坐标。
                document.onmousemove = function (event) {

                    div01.style.left = event.clientX - x + 'px';
                    div01.style.top = event.clientY - y + 'px';
                };

                // 给document绑定鼠标松开的事件,松开之后删除document的鼠标移动事件和鼠标松开事件。
                // 这里需要将鼠标松开事件绑定为document,不能绑定为div01,因为如果将div01移动到其他div(div01的兄弟)下,
                // div01的鼠标松开事件onmouseup是无法触发的,所以需要绑定给document。同时由于事件冒泡的特性,
                // 及时就是div01移动到其他div下,鼠标的松开事件也会传导给document。
                document.onmouseup = function () {
                    document.onmousemove = null;
                    document.onmouseup = null;
                }
            };
        }
    </script>
</head>
<body>

<div id="div01"></div>
<div id="div02"></div>
</body>
</html>

7.事件的委派

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>01-事件的委派</title>
    <script>
        window.onload = function () {
            // 1 将点击事件绑定给了a标签,如果新增一个a标签,就需要给新增的a设置点击事件。
            // let items = document.getElementsByTagName('a');
            // for (let i = 0;i < items.length;i++) {
            //     items[i].addEventListener('click', function () {
            //         alert('点击了a');
            //     })
            // }

            // 2 添加btn01后,给ul中添加一个同样的ul,这时a标签就需要设置点击事件。
            // 解决增加新的ul后需要设置点击事件的办法,将点击事件绑定给ul,这时由于事件的冒泡,点击a之后就会传递给ul。
            let ul = document.getElementsByTagName('ul')[0];
            document.getElementById('btn01').onclick = function () {
                ul.insertAdjacentHTML('beforeend', '<li><a href="javascript:;">新超链接</a></li>');
            };

            // 3 事件的委派:当需要为多个函数绑定相同的响应事件时,可以将响应事件绑定到他们共同的祖先元素。
            // 这样只需要绑定一次就可以让所有的元素都拥有响应事件,即使元素是新添加的也会拥有响应事件。

            // 4 给ul绑定点击事件之后存在的问题:我们只希望点击ul中的a标签时触发点击事件,
            // 但是给ul绑定点击事件后,点击ul也触发了点击事件。解决办法:通过event.target来
            // 获取触发事件的对象,然后进行判断。
            ul.addEventListener('click', function (event) {
                // event.target 获取触发事件的对象。
                // event.target.tagName 获取触发事件对象后,在获取这个对象的标签名,即只有当点击a标签之后才
                // 触发点击事件。
                if (event.target.tagName.toUpperCase() === 'A') {
                    alert('点击了a');
                }
            })
        }
    </script>
</head>
<body>

<button id="btn01">btn01</button>
<button id="btn02">btn02</button>
<ul>
    <li>
        <a href="javascript:;">超链接</a>
    </li>
    <li>
        <a href="javascript:;">超链接</a>
    </li>
    <li>
        <a href="javascript:;">超链接</a>
    </li>
</ul>
</body>
</html>

8.JavaScript修改标签的class属性

<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        .b1 {
            width: 100px;
            height: 100px;
            background-color: red;
        }

        .b2 {
            width: 200px;
            height: 200px;
            background-color: orange;
        }
    </style>
    
    <script>
        window.onload = function () {
            document.getElementById('btn01').onclick = function () {

                let div01 = document.getElementById('div01');
                // 切换class,可以通过classList来修改class属性。
                // 1 classList的类型是DOMTokenList。
                // 2 classList的常用方法。
                //      add() 向元素添加一个或者多个类,如果元素中已经要添加的类,则不会重复添加。
                //      remove() 用来移除元素中的类。
                //      replace() 使用一个新的类替换原有的类。
                //      toggle() 切换元素的类。如果元素有这个类,则删除;没有,则添加。
                //      contains() 元素中是否包含这个类。
                let classList = div01.classList;

                //classList.add('b2');
                //classList.remove('b1');
                //classList.replace('b1', 'b2');
                classList.toggle('b2');
                console.log(classList.contains('b2'));
            }
        }
    </script>
</head>
<body>
<button id="btn01">btn01</button>
<div class="b1" id="div01"></div>
</body>
</html>

9.练习-div随鼠标移动,解决选择文字时,div移动出现的问题

<head>
    <meta charset="UTF-8">
    <style>
        #div01 {
            width: 100px;
            height: 100px;

            border: 1px solid black;
            background-color: orange;
            position: absolute;
        }

        #div02 {
            width: 100px;
            height: 100px;

            margin-left: 500px;
            margin-top: 100px;
            border: 1px solid black;
            background-color: black;
            position: absolute;
        }
    </style>

    <script>
        window.onload = function () {
            let div01 = document.getElementById('div01');

            div01.onmousedown = function (event) {
                // 当我们选中文字并进行拖拽时,浏览器会尝试将文字在搜索引擎中搜索,
                // 这是浏览器的默认行为,会影响到拖拽功能。
                // 可以通过取消浏览器的默认拖拽文字的行为来解决这个问题。
                event.preventDefault();

                let x = event.clientX - div01.offsetLeft;
                let y = event.clientY - div01.offsetTop;

                document.onmousemove = function (event) {

                    div01.style.left = event.clientX - x + 'px';
                    div01.style.top = event.clientY - y + 'px';
                };

                document.onmouseup = function () {
                    document.onmousemove = null;
                    document.onmouseup = null;
                }
            };
        }
    </script>
</head>
<body>
hello hello
<div id="div01"></div>
<div id="div02"></div>
</body>
</html>

10.练习-div随鼠标移动代码封装

<html lang="en">
<head>
    <meta charset="UTF-8">
    <style>
        #div01 {
            width: 100px;
            height: 100px;

            background-color: orange;
        }
        #div02 {
            width: 100px;
            height: 100px;

            background-color: red;
        }
        #div03 {
            width: 100px;
            height: 100px;
            
            background-color: black;
        }

        .drag {
            position: absolute;
        }
    </style>
</head>
<body>

<div id="div01" class="drag"></div>
<div id="div02" class="drag"></div>
<div id="div03" class="drag"></div>

<script>
    (function () {
        // 封装div随鼠标移动的功能,只要div中包含drag属性,就可以随鼠标进行移动。
        let target = null;
        let left, top;

        document.addEventListener('mousedown', function (event) {
            // 元素包含drag属性才触发。
            if (event.target.classList.contains('drag')) {
                event.preventDefault();

                target = event.target;
                left = event.clientX - target.offsetLeft;
                top = event.clientY - target.offsetTop;
            }
        });

        // 给document绑定鼠标移动事件
        document.addEventListener('mousemove', function (event) {
            // 发送了鼠标按下事件才触发。
            if (target) {
                target.style.left = event.clientX - left + 'px';
                target.style.top = event.clientY - top + 'px';
            }
        });

        // 给document绑定鼠标松开事件
        document.addEventListener('mouseup', function () {
            target = null;
        })
    })();
</script>
</body>
</html>
posted @ 2022-08-27 11:52  行稳致远方  阅读(27)  评论(0)    收藏  举报