• JavaScript基础09——事件驱动


    1.事件驱动

    js控制页面的行为是由事件驱动的。
        
        什么是事件?(怎么发生的)
        事件就是js侦测到用户的操作或是页面上的一些行为
     
        事件源(发生在谁身上)
        引发事件的元素
     
        事件处理程序(发生了什么事)
        对事件处理的程序或函数
     
        事件对象(用来记录发生事件时的相关信息)
     只有在事件发生的时候,才会产生事件对象,无法手动创建,并且事件对象只能在处理函数内部访问,处理函数允许结束后该对象自动销毁
     

    2. 事件的分类:

        鼠标事件:
            onclick        单击
            ondblclick     双击
            onmousedown    按下
            onmouseup      抬起
            onmousemove    移动
            onmouseover    放上去        onmouseenter    进入
            onmouseout     离开          onmouseleave    离开
     
            onmousewheel   滚轮事件
     
            onmouseenter和onmouseleave不支持事件冒泡
            
        表单事件:
            onsubmit       提交
            onfocus        获得焦点
            onblur         失去焦点
            onchange       改变文本区域的内容
     
        页面事件:
            onload         加载完成
    。。。
    在W3C标准中:事件可以写在行内,但是因为结构和行为要分离,所以我们一半情况下用JS的方法来绑定事件,只有在极少数情况下,才将事件写在行内。
        行内事件又叫:HTML事件处理程序
     

    3.事件对象的概念和作用

        1.事件有对象!叫事件对象(event)
        2.事件对象是浏览器给的
        3.事件对象不叫不出来
     
        什么是event事件对象?
        用来记录一些事件发生时的相关信息的对象,每次事件发生的时候,会在函数或方法内部产生一个事件对象,这个事件对象就是event。
     
        特征:
            1.只有当事件发生的时候才会产生,只能在处理函数内部访问
            2.处理函数运行结束后自动销毁

    获取方式(兼容问题)

    document.onclick = function(eve){
           var e = eve || window.event;
           console.log(e);
       }
    注意:event需要逐层传递,不要疏忽外部的function

    自定义右键菜单

    下面是自定义右键菜单的案例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style type="text/css">
            body {
                font-size: 16px;
                font-family: "KaiTi";
            }
            ul {
                list-style: none;
                margin:0;
                padding: 0;
            }
            a {
                text-decoration: none;
                color: #333;
            }
            .contextmenu {
                 200px;
                border: 1px solid #999;
                box-shadow: 3px 3px 3px #ccc;
                background-color: #fff;
                position: absolute;
                top: 10px;
                left: 10px;
                display: none;
            }
            .contextmenu li  {
                height: 38px;
                line-height: 38px;
            }
            .contextmenu li a {
                display: block;
                padding:0 20px;
            }
            .contextmenu li a:hover {
                background-color: #ccc;
                color: white;
                font-weight: bold;
            }
        </style>
    </head>
    <body>
    <div class="contextmenu" id="context">
        <ul>
            <li><a href="javascript:;">复制</a></li>
            <li><a href="javascript:;">粘贴</a></li>
            <li><a href="javascript:;">剪切</a></li>
            <li><a href="javascript:;">获取种子</a></li>
            <li><a href="javascript:;">迅雷下载</a></li>
        </ul>
    </div>
    </body>
    <script>
        // 先来获取菜单列表,然后让其在鼠标右击的时候显示出来
        document.oncontextmenu = function (ob) { // ob 表示event事件
    
            // 兼容event事件
            var e = ob || window.event;
    
            // 首先获取菜单
            var context = document.getElementById('context');
            // 让菜单显示出来
            context.style.display = "block";
    
    
            // 让菜单跟随鼠标位置而移动
            // 需要使用鼠标的坐标,让鼠标的坐标位置为菜单的左上角0,0
            var x  = e.clientX;
            var y = e.clientY;
    
    
            // 获取窗口的宽度和高度(在浏览器中的可用窗口宽度和高度,当调整窗口大小的时候,获取的值也会变)
            var w = window.innerWidth;
            var h = window.innerHeight;
            console.log("窗口宽度为:"+w,"窗口的高度为:"+h);
    
    
            // 将获得的值赋值给菜单的右键菜单,从而实现让右键菜单会出现在鼠标的位置上
            // context.style.left = x + 'px';
            // context.style.top = y + 'px';
            // 重新调整宽度和高度
            context.style.left =Math.min(w - 202,x) + 'px';
            context.style.top = Math.min(h - 230,y) + 'px';
    
    
            // 通过return false关闭系统默认菜单
            return false;
        }
        // 当鼠标单击之后,希望关闭右键菜单
        document.onclick = function () {
            var contextmenu = document.getElementById('context');
            // 让菜单在单击之后消失
            contextmenu.style.display = 'none';
        }
    </script>
    </html>

    4.鼠标事件常用属性介绍

        检测按下的鼠标按键:event.button
        返回值为0,左键;返回值为1,中键;返回值为2,右键
     
        检测相对于浏览器的位置:clientX和clientY
        当鼠标事件发生时,鼠标相对于浏览器左上角的位置
        
        检测相对于文档的位置:pageX和pageY
        当鼠标事件发生时,鼠标相对于文档左上角的位置。(IE7/8无)(类似于event.clientX和event.clientY)
     
        检测相对于屏幕的位置:screenX和screenY
        当鼠标事件发生时,鼠标相对于屏幕左上角的位置
     
        检测相对于事件源的位置:offsetX和offsetY
        当鼠标事件发生时,鼠标相对于事件发生元素左上角的位置
     

    获取鼠标坐标

    通过evnet对象当中的内容,我们可以非常轻易的获取鼠标的坐标。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    </body>
    <script>
        document.onmousemove = function (env) {
            var env = env || window.event;
            console.log(env.clientX,env.clientY); // clientX 鼠标x轴坐标,clientY鼠标y轴坐标
        }
    </script>
    </html>
     根据鼠标事件和event对象来完成一个案例:图层拖拽。
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>图层拖拽</title>
        <style type="text/css">
            .box {
                200px;
                height: 200px;
                background-color: orange;
                border: 2px solid pink;
                cursor: pointer;
                position: absolute;
                left:100px;
                top: 20px;
            }
        </style>
    </head>
    <body>
    <h1>图层拖拽</h1>
    <hr>
    <div class="box" id="box"></div>
    </body>
    <script type="text/javascript">
    
        // 获取元素绑定事件
        var oBox = document.getElementById("box");
        oBox.onmousedown = function (env) {
            var env = env || window.event;
    
            // 获取一下鼠标在div上的位置
            var left = env.clientX - oBox.offsetLeft;
            var top = env.clientY - oBox.offsetTop;
    
            // 为了方便查看效果,当鼠标点击之后,改变一下颜色
            oBox.style.background = "#999";
    
            oBox.onmousemove = function (env) {
                var env = env || window.event;
    
                var x = env.clientX;
                var y = env.clientY;
                oBox.style.left = (x - left) + 'px';
                oBox.style.top = (y - top) + 'px';
            }
    
    
        }
    
        oBox.onmouseup = function () {
            oBox.style.background = "orange";
            oBox.onmousemove = function (){}
        }
    
    </script>
    </html>

     5.键盘事件(keyup/keydown/keypress)

        键盘事件:
            onkeydown      键盘按下
            onkeyup        键盘抬起
            onkeypress     按下并抬起数字字母按键
        event.keyCode        返回当前按键的ASCII码
     
            空格    32
            回车    13
            左      37
            上      38
            右      39
            下      40
     
        兼容问题:  var eve = eve || window.event
                  var keyC = eve.keyCode || eve.which
     
        案例:通过键盘上下左右,控制页面中的元素位置移动
     
        ctrlKey        判断ctrl是否被按下,按下返回true
        shiftKey       判断shift是否被按下,按下返回true
        altKey         判断alt是否被按下,按下返回true
     
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    </body>
    <script>
        document.onkeydown = function (env) {
            var env = env || window.event;
            console.log(env); // KeyboardEvent
        }
    </script>
    </html>

    兼容性问题:

    IE:

    支持keyCode

    不支持which和charCode,二者值为 undefined

    在Firefox下:

    支持keyCode,除功能键外,其他键值始终为 0

    支持which和charCode,二者的值相同

    在Opera下:

    支持keyCode和which,二者的值相同

    不支持charCode,值为 undefined

    6.器的默认行为

    很多时候,我们的浏览器都具备一些默认的行为,这些默认的行为在某些时刻我们需要取消或者屏蔽掉,例如当我们在我们自己的网页中自定义了右键菜单,那么我们就希望屏蔽掉浏览器的右键菜单,所以我们可以如下

    document.oncontextmenu = function () {
            return false;
        }
    其他写法及兼容
    //阻止浏览器的默认行为 
    function stopDefault( e ) { 
        //阻止默认浏览器动作(W3C) 
        if ( e && e.preventDefault ) 
            e.preventDefault(); 
        //IE中阻止函数器默认动作的方式 
        else 
            window.event.returnValue = false; 
        return false; 
    }

     7.冒泡

    事件流:事件执行顺序我们叫他事件流。
        事件流中事件冒泡的由来:IE公司认为,如果你面前有个靶子,你的飞镖射中了其中一环,并不仅仅是只对这一环产生了操作,而是对整个靶子都产生了操作。
        所以,当最里面的元素触发了事件的时候,会依次向上触发所有元素的相同事件(从触发事件的元素开始一直向上触发),但是事件冒泡对我们几乎没有任何好处,所以我们需要阻止事件冒泡。
     
     
        eve.stopPropagation();            
        eve.cancelBubble = true;        //兼容IE
    案例:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            div {
                padding:40px;
            }
            #div1 {
                background-color: red;
            }
            #div2 {
                background-color: pink;
            }
            #div3 {
                background-color: orange;
            }
        </style>
    </head>
    <body>
    <div id="div1">
        <div id="div2">
            <div id="div3"></div>
        </div>
    </div>
    </body>
    <script>
        var d1 = document.getElementById('div1');
        var d2 = document.getElementById('div2');
        var d3 = document.getElementById('div3');
    
        function fn1() {
            alert(this.id);
        }
    
        // 绑定事件
        d1.onclick = fn1;
        d2.onclick = fn1;
        d3.onclick = fn1;
    </script>
    </html>

     8.事件监听器(兼容)

        事件触发阶段主要由于事件流:DOM0级事件处理阶段和DOM2级事件处理;
     
        DOM0级事件处理,是一种赋值方式,是被所有浏览器所支持的,简单易懂容易操作;
            元素.onclick = function(){}
     
        DOM2级事件处理是所有DOM节点中的方法,可以重复绑定,但是浏览器兼容存在问题;
     
        非IE下:(这里的事件名不带on),第三个参数表示是在捕获阶段还是冒泡阶段。可以重复绑定事件,执行顺序按照绑定顺序来执行。
     
        oDiv.addEventListener('click',fn,false);
        oDiv.removeEventListener('click',fn ,false);
     
        IE下:
     
        只有冒泡阶段,所以没有第三个参数;(这里的事件名需要加on)
        oDiv.attachEvent();
        oDiv.detachEvent() ;
     
    冒泡:从下往上(从里往外)
    捕获:从上往下(从外往内)
     
    2.封装成两个函数的方式
        function addEvent(obj,inci,back){
            if(obj.addEventListener){
                obj.addEventListener(inci,back);
            }else if(obj.attachEvent){
                obj.attachEvent("on" + inci,back);
            }else{
                obj["on"+inci] = back;
            }
        }
              
        function removeEvent(obj,inci,back){
            if(obj.removeEventListener){
                obj.removeEventListener(inci,back,false);
            }else if(obj.detachEvent){
                obj.detachEvent("on" + inci,back);
            }else{
                obj["on"+inci] = null;
            }
        }

     事件委托机制

        通过e.target获取触发事件的事件源
    
        利用事件冒泡原理,将绑定在多个子元素身上的相同事件,绑定在页面上现存的父元素身上。
    
    
            oul.onclick = function(eve){
                 var e = eve || window.event;
                 var target = e.target || e.srcElement;
                 if(target.nodeName == "LI"){
                     console.log(target.innerHTML);
                 }
             }
    优势:
        1.节省性能
        2.可以给页面上暂时不存在的元素绑定事件
     事件流的三种状态:
        事件冒泡
        事件捕获
        目标阶段
     
     

    ------------恢复内容结束------------

    2.封装成两个函数的方式
        function addEvent(obj,inci,back){
            if(obj.addEventListener){
                obj.addEventListener(inci,back);
            }else if(obj.attachEvent){
                obj.attachEvent("on" + inci,back);
            }else{
                obj["on"+inci] = back;
            }
        }
              
        function removeEvent(obj,inci,back){
            if(obj.removeEventListener){
                obj.removeEventListener(inci,back,false);
            }else if(obj.detachEvent){
                obj.detachEvent("on" + inci,back);
            }else{
                obj["on"+inci] = null;
            }
        }
  • 相关阅读:
    C# Winform 运行异常 CefSharp.core.dll 找不到指定的模块
    WCF TCP通信方式 通过IIS承载调试
    [译]Modern Core Graphics with Swift系列
    博客搬家
    [ios] 定位报错Error Domain=kCLErrorDomain Code=0 "The operation couldn’t be completed. (kCLErrorDomain error 0.)"
    [IOS] 'Double' is not convertible to 'CGFloat'
    [IOS]swift 使用AVOS的API
    [IOS]使用了cocoapods 抱错Pods was rejected as an implicit dependency for ‘libPods.a’ because its architectures ......
    [IOS]cocoapos 两个ruby源的对比
    [IOS]Swift 遍历预制的本地资源文件
  • 原文地址:https://www.cnblogs.com/wuziqiang/p/12076461.html
Copyright © 2020-2023  润新知