Web前端Javascript笔记(5)事件

1. 什么是事件:事件是指发生并得到处理的操作

JavaScript中的事件是由访问web页面的用户引起的一系列操作,例如,用户的点击操作,JavaScript中有两种事件模型:内联模型,脚本模型。

内联模型:是一种传统简单的事件处理方法,在内联模型中,事件处理函数是HTML标签的一个属性,用于处理指定事件。特点:是和html代码混写在一起的。

脚本模型:将事件绑定与HTML代码分离开来:

事件的绑定方式:内联模式,脚本模式

在开发中,推荐使用外联(脚本)模式,这样可以将HTML于CSS完全分离

事件类型:

1. 鼠标事件

    click:   单击

    dblclick:双击

    mouseover:鼠标移入,在经过元素子节点的时候也会触发

    mouseout:鼠标移出

    mousemove: 鼠标移动  (不停的触发)

    mousedown:鼠标按下

    mouseup:鼠标抬起

    mouseenter:  鼠标移入  ,在经过元素子节点的时候不会触发

    mouseleave: 鼠标移除

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function(){
            let btn = $("btn1");
            btn.ondblclick = function () {
                alert("double click");
            };
            btn.onmouseover = function () {
                this.style.background = "#996e27";
            };
            btn.onmouseout = function () {
                this.style.background = "white";
            };

            let cnt = 0;
            let box = $("box");
            box.onmousemove = function () {
                this.innerHTML = cnt++;
            }
            

        }
    </script>
    <style>
        #box{
            width: 200px;
            height: 200px;
            background: red;
        }
    </style>
</head>
<body>
    <button id="btn1">按钮</button>
    <div id="box">0</div>
</body>
</html>

效果如下所示:

2.键盘事件(一般绑定在表单元素或者window)

keydown:键盘按下,如果不松开的话,会一直触发事件

keyup:键盘抬起

keypress:键盘按下,只支持字符键

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function(){
            let i = 0;
            window.onkeydown = function () {
                document.title = (i++).toString();
            };
            window.onkeyup = function () {
                document.title = "抬起"
            };
            window.onkeypress = function (key) {
                // 传入的参数:可以得到具体的按键值
                alert(key.code);
            }
        }
    </script>
</head>
<body>

</body>
</html>

3.HTML事件

   a. window事件

       load:当页面加载完毕后会触发的事件

       unload:当页面解构的时候会触发的事件,例如刷新页面,或者关闭页面 ,只支持IE浏览器

       scroll:页面滚动的时候触发事件

       resize:窗口大小发生变化的时候触发的事件

   b. 表单事件

       blur :  失去焦点

       focus  :获得焦点

       select:当在输入框内选中文本的时候会触发的事件

       change:  当对输入框的文本进行修改且失去焦点的时候会触发事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function(){
            let input_tag = $("username");
            input_tag.onblur = function(){
                alert("失去焦点");
            };
            input_tag.onfocus = function () {
                alert("获得焦点");
            };
            input_tag.onchange = function () {
                alert("内容修改");
            };
            input_tag.onselect = function () {
                alert("内容选中");
            };

        }
    </script>
</head>
<body>
    <input id="username" type="text" placeholder="请输入用户名">
</body>
</html>

       【注】下面两个自能添加到form元素上

        submit: 当点击submit上的按钮时才能出发

        reset: 当点击reset上的按钮时才能出发

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function(){
            let form = $("userInfo");
            let input_box = form.firstElementChild;
            form.onsubmit = function () {
                if(!input_box.value){
                    alert("用户名不能为空");
                }
                else
                {
                    alert("注册成功");
                }
            };
            form.onreset = function () {
                input_box.value = "";
                alert("重置")
            };
        }
    </script>
</head>
<body>
    <form id="userInfo">
        <input type="text" placeholder="请输入">
        <input type="submit">
        <input type="reset">
    </form>
</body>
</html>

事件对象:

在上述的事件绑定的过程中,当元素与标签之间的事件绑定一旦完成的时候,系统会自动生成一个事件对象,当事件触发的时候,系统会去调用相应的事件函数,此时,系统会将事件对象当作第一个参数传入。

例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        function show(){
            alert(arguments.length);
            alert(arguments[0]);
        }

        window.onload = function(){
            let button_tag = $("btn");
            button_tag.onclick = show;
        };
    </script>
</head>
<body>
    <button id="btn">按钮</button>
</body>
</html>

例如,在触发按钮事件之后,系统会调事件函数show()(show函数只能由系统调用),可以在show()函数中输出函数参数,可以看到,系统给show()函数传入了一个参数:

可以看到传入的是一个MouseEvent事件对象。

可以在函数申明中定义一个形参,用来接收系统传入的参数,但是此方法只有在IE8以上的浏览器中才兼容,还有一种方法,可以在定义的函数中通过window.event拿到系统传入的参数,所以可以写一个兼容不同版本浏览器的函数:

<script>
        function show(ev){
            let e = ev || window.event;
            alert(e);
        }

        window.onload = function(){
            let button_tag = $("btn");
            button_tag.onclick = show;
        };
</script>

事件对象属性和方法:

a. 鼠标事件对象:

button:  表示按下的是鼠标的哪个键 0 1 2 = 【左,中,右】

获取当前鼠标位置:三种方法:(原点位置不一样)

clientX, clientY   原点位置为可视窗口的左上角,即使页面滚动了,参考原点依然是左上角的可视区域

pageX, pageY    原点位置为页面的左上角,页面滚动,相应的y坐标也会增加

screenX, screenY  原点位置为电脑屏幕的左上角,即使浏览器出了电脑屏幕,坐标的参考原点依然为屏幕左上角

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function () {
            document.onmousedown = function (ev) {
                // 鼠标按下的事件
                let e = ev || window.event;   // 获取事件对象
                alert(e.button);     // 获取鼠标的按键
                alert(e.clientX + "," + e.clientY);
                alert(e.pageX + "," + e.pageY);
                alert(e.screenX + "," +e.screenY);
            };
        }
    </script>
</head>
<body>

</body>
</html>

案例:

可以跟随鼠标移动的提示框

所以需要实现的是:

1. 鼠标移入,展现出提示框

2. 鼠标移动,提示框随着鼠标移动

3. 鼠标移出,提示框消失

步骤:

1. 先给a标签添加鼠标移入和移除事件,再添加鼠标移入事件。

2. 在获取到鼠标的当前坐标之后,需要给坐标添加一定量的偏置,在把偏置后的坐标作为div的位置,因为div的层级高于a标签,所以如果不偏置,鼠标在div上时,就相当于移出了a标签,这样就会反复触发mouseover和mouseout事件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function () {
            let tag_a = document.getElementsByTagName("a");  // 所有的a标签
            let content_box = $("msg");
            let content_arr = ["Go for html", "go for python", "go for C++"];
            for (let i=0; i<tag_a.length; i++)
            {
                tag_a[i].index = i;
                tag_a[i].onmouseover = function () {
                    content_box.style.display = "block";
                    content_box.innerHTML = content_arr[i];
                };
                tag_a[i].onmouseout = function () {
                    content_box.style.display = "none";
                };

                tag_a[i].onmousemove = function (position) {
                    let pos = position || window.event;    // 获取事件对象
                    let cord_x = pos.clientX + 5;  // 添加5像素的偏置量
                    let cord_y = pos.clientY + 5;
                    content_box.style.left = cord_x + "px";
                    content_box.style.top = cord_y + "px";
                };
            }

        }
    </script>
    <style>
        a{
            font-size: 25px;
            color: blue;
            display: block;
            border: none;
            /*width: 200px;*/
            /*height: 100px;*/
            margin-left: 30px;
            margin-top: 100px;
            width: 50px;
        }
        #msg{
            width: 200px;
            height: 80px;
            border: 1px solid black;
            display: none;
            background: gray;
            position: absolute;
        }
    </style>
</head>
<body>
    <a href="#">Html</a>
    <a href="#">python</a>
    <a href="#">c++</a>
    <div id="msg"></div>
</body>
</html>

事件对象属性:

shiftkey  : 按下shift键时为true, 否则为false

altkey:按下alt键为true,否则为false

ctrlkey: 

metakey:windows下为windows键

键盘事件中的属性:
keyCode也需要兼容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function () {
            window.onkeydown = function (ev) {
                let e = ev || window.event;
                alert(e);
                // 获取键码,需要考虑不同浏览器的兼容问题
                let which = e.which || e.keyCode;
                alert(which);
            }
        }
    </script>
</head>
<body>

</body>
</html>

对前面的内容发布的程序进行修改,添加快捷键,在输入框中输入内容,按下ctrl+enter键,也可以发布内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function () {
            let input_tag = $("input_text");
            let bottom_section = $("bottom");
            $("add").onclick = function ()
            {
                let input_content = input_tag.value;
                if(!input_content){
                    alert("请输入内容");
                }
                else{
                    // 开始创建节点
                    let node = document.createElement("div");
                    let text_node = document.createTextNode(input_content);
                    let btn_node = document.createElement("button");
                    let btn_text_node = document.createTextNode("x");
                    btn_node.appendChild(btn_text_node);
                    node.appendChild(text_node);
                    node.appendChild(btn_node);
                    node.style.background = randomColor();
                    bottom_section.appendChild(node);
                    input_tag.value = "";   // 清空输入框
                    updateItemsButtons();
                }
            };

            $("delete").onclick = function () {
                let last_node = bottom_section.lastChild;
                bottom_section.removeChild(last_node);
                updateItemsButtons();
            };

            $("clone").onclick = function () {
                let last_node = bottom_section.lastChild;
                let clone_node = last_node.cloneNode(true);   // 深拷贝
                bottom_section.appendChild(clone_node);
                updateItemsButtons();
            };

            function updateItemsButtons() {
                // 对每条记录上的删除按钮绑定函数
                let child_nodes = bottom_section.children;  // 只获取div元素节点
                let btn_arr = [];
                for(let i=0; i<child_nodes.length; i++)
                {
                    btn_arr.push(child_nodes[i].firstElementChild);
                    //console.log(child_nodes[i].children);
                }
                // 对标签绑定事件函数
                for (let i=0; i<btn_arr.length; i++)
                {
                    // console.log(btn_arr[i]);
                    btn_arr[i].index = i;
                    btn_arr[i].onclick = function () {
                        bottom_section.removeChild(child_nodes[this.index]);
                    }
                }
            }
            input_tag.onkeydown = function (ev)
            {
                // 给输入框添加快捷键
                let e = ev || window.event;
                let key_code = e.keyCode || e.which;   // 判断回车键
                if(e.ctrlKey && key_code===13)
                {
                    $("add").onclick();
                }
            }
        }

    </script>
    <style>
        #container{
            width: 200px;
            border: 1px solid black;
        }
        #top{
            width: 100%;
            height: 30px;
        }
        #top input{
            height: 20px;
            line-height: 30px;
            margin: 0 auto;
        }
        #middle{
            width: 100%;
            height: 50px;
            border: none;
            display: flex;
            flex-direction: row;
            justify-content: space-around;
            background: #0f6674;
        }
        #middle button{
            /*width: 25%;*/
            height: 50%;
            align-self: center;
            /*margin-top: 10px;*/
        }

        #bottom{

        }

        #bottom div{
            height: 25px;
            position: relative;
        }
        #bottom div button{
            position: absolute;
            top: 1px;
            right: 2px;
        }
    </style>
</head>
<body>
    <div id="container">
        <div id="top">
            <input type="text" id="input_text" placeholder="请输入内容">
        </div>
        <div id="middle">
            <button id="add">添加</button>
            <button id="delete">删除</button>
            <button id="clone">克隆</button>
        </div>
        <div id="bottom">
            <!--<div>content<button>x</button></div>-->
        </div>
    </div>
</body>
</html>

效果如下所示:

事件冒泡和触发对象:

事件属性target表示触发对象,只有IE8以上的浏览器兼容,需要和window.event.srcElement方法兼容使用

触发对象表示的是这个事件是由谁而触发引起的:,例如下面的div标签:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function () {
            $("cox").onclick = function (ev) {
                alert(this.innerHTML);    // 输出1233
                // 获取触发对象
                let e = ev || window.event;   // 获取事件对象
                let target = e.target || window.event.srcElement;  // 事件对象的target属性表示触发对象
                alert(target.innerHTML);
            }
        }
    </script>
</head>
<body>
    <div id="cox">1233</div>
</body>
</html>

上述的两种方法输出的都是1233,但是,实际上this 和 targe实质上是不同的。this指向的是当前的标签,而target指向的是触发事件的标签,这个标签有可能是当前的标签,也可能是当前标签的子标签,例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function () {
            $("cox").onclick = function (ev) {
                alert(this.tagName);    // 输出1233
                // 获取触发对象
                let e = ev || window.event;   // 获取事件对象
                let target = e.target || window.event.srcElement;  // 事件对象的target属性表示触发对象
                alert(target.innerHTML);
            }
        }
    </script>
</head>
<body>
    <ul id="cox">
        <li>11111</li>
        <li>22222</li>
    </ul>
</body>
</html>

例如,this.tagName输出的是UL标签,因为UL是事件函数的主人,但是这里的target表示的具体点击的<li>标签,代表的是触发时间函数的那个对象。

事件冒泡:

存在于嵌套的标签中,当嵌套的标签内外都绑定了时间函数的时候,内部的事件函数被触发执行完毕后,外部的标签又会被触发。这就是事件冒泡。

例如,对于下面的三个<div>标签:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function () {
            let tags = document.getElementsByTagName("div");
            for (let i=0; i<tags.length; i++)
            {
                tags[i].onclick = function () {
                    alert(this.id);
                }
            }
        }
    </script>
    <style>
        div{
            padding: 30px;
        }
        #div1{
            background: red;
            width: 200px;
            height: 200px;
        }
        #div2{
            background: green;
            width: 60%;
            height: 60%;
            margin: 0 auto;
        }
        #div3{
            background: blue;
            width: 60%;
            height: 60%;
            margin: 0 auto;
        }
    </style>
</head>
<body>
    <div id="div1">
        <div id="div2">
            <div id="div3"></div>
        </div>
    </div>
</body>
</html>

当点击div2的时候,会触发div2事件函数,之后又会触发div1事件函数。当点击div3的时候,触发div3事件函数,之后又触发div2事件函数,接着又会触发div1事件函数。

事件冒泡又称为事件流:事件由里向外,逐层触发。很多时候,并不想让浏览器发生事件冒泡,阻止事件冒泡的方法有两种:

cancelBubble = True和 stopPropagation(),这些都是事件对象的属性和方法,所以首先需要拿到事件对象:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function () {
            let tags = document.getElementsByTagName("div");
            for (let i=0; i<tags.length; i++)
            {
                tags[i].onclick = function (ev) {
                    let e = ev || window.event;
                    //e.cancelBubble = true;    // 阻止事件冒泡
                    // e.stopPropagation();
                    // 跨浏览器兼容:
                    stopBubble(e);
                    alert(this.id);
                }
            }

            // 跨浏览器兼容
            function stopBubble(e) {
                if(e.stopPropagation)
                {
                    e.stopPropagation();
                }
                else{
                    e.cancelBubble = true;
                }
            }
        }
    </script>
    <style>
        div{
            padding: 30px;
        }
        #div1{
            background: red;
            width: 200px;
            height: 200px;
        }
        #div2{
            background: green;
            width: 60%;
            height: 60%;
            margin: 0 auto;
        }
        #div3{
            background: blue;
            width: 60%;
            height: 60%;
            margin: 0 auto;
        }
    </style>
</head>
<body>
    <div id="div1">
        <div id="div2">
            <div id="div3"></div>
        </div>
    </div>
</body>
</html>

案例练习: 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script rel="script" src="../JavaScript/tool.js"></script>
    <script>
        window.onload = function () {
            let divs = document.getElementsByTagName("div");
            document.onmousemove = function (ev)
            {
                let e = ev || window.event;
                for (let i=divs.length-1; i>0; i--)
                {
                    divs[i].style.left = divs[i-1].offsetLeft + "px";
                    divs[i].style.top = divs[i-1].offsetTop + "px";
                }
                divs[0].style.left = e.clientX + "px";
                divs[0].style.top = e.clientY + "px";
            };
        }
    </script>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        div{
            position: absolute;
            width: 10px;
            height: 10px;
            background: black;
            border-radius: 50%;
        }
    </style>
</head>
<body>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</body>
</html>

 

posted @ 2020-03-27 15:22  Alpha205  阅读(131)  评论(0编辑  收藏  举报