zoukankan      html  css  js  c++  java
  • JavaScript DOM高级程序设计 4.3控制事件流和注册事件侦听器--我要坚持到底!

    • 一、事件流

    我们通过下面一个实例,进行说明。

    <body>
    <h1>Event Flow</h1>
    <ul id="nav">
        <li><a href="../image-load/image-load.html">Image-Load</a></li>
        <li><a href="../click/click.html">Click</a></li>
        <li><a href="../move/move.html">Move</a></li>
        <li><a href="../address/address.html">Address Form</a></li>
        <li><a href="../follow/follow.html">Follow</a></li>
        <li><a href="../flow/flow.html">Flow</a></li>
        <li><a href="../keys/keys.html">Key Press</a></li>
        <li><a href="../load/load.html">addLoadEvent</a></li>
    </ul>
    <div id="content">
        <ul id="list1">
            <li>
                <p>List 1 </p>
                <ul id="list2">
                    <li>
                        <p>List 2 </p>
                        <ul id="list3">
                            <li>
                                <p>List 3 </p>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
        
        <ul id="list4">
            <p>List 4 </p>
        </ul>
    </div>
    </body>

    提供的CSS样式通过设置第三个嵌套列表的位置,使其在视觉上处于祖先元素之外、且位于第四个列表之上

    #list1 {
        height:80px;
    }
    #list2 {
        margin-top: 10px;
        height:20px;
    }
    
    #list3 {
        position:absolute;
        top:190px;
        left:150px;
    }
    
    #list4 {
        margin-top:10px;
        height:100px;
    }
    //主要任务就是修改被单击元素的属性
    addEvent(window,'load',function(){
        //为了演示问题所在,使用一个修改后的addEvent方法
        function modifiedAddEvent(obj,type,fn)
        {
            if (obj.addEventListener)
            {
                //W3C方式
                /*这个方法在第一章的addEvent()方法基础上进行修改,
                修改后启用了捕获阶段而取消了冒泡阶段*/
                obj.addEventListener(type,fn,true);
            }
            else if (obj.attachEvent)
            {
                //ms 方式
                obj['e'+type+fn]=fn;
                obj[type+fn]=function(){obj['e'+type+fn](window.event);}
                obj.attachEvent('on'+type,obj[type+fn]);
            }
            else
            {
                return false;
            }
        }
        var counter=0;
    
        //取得无序列表
        var lists=document.getElementsByTagName('ul');
        for (var i = 0 ;i<lists.length ;i++ )
        {
            //注册单机事件侦听器
            modifiledAddEvent(lists[i],'click',function(){
                //向段落添加表示捕获单机事件先后顺序的数字
                var append=document.createTextNode(':'+counter++);
                this.getElementsByTagName('p')[0].appendChild(append);
    
                //修改类名以突出显示被单击的元素
                this.className='clicked';
            });
            
        }
    });

    老实说,我现在又到了没有耐心的时刻了,看书看不下去。所以上文看的也是迷迷糊糊。但是想到,我一定要坚持下去,我不能浮躁。要不我今天先休息。明天继续学习。//我还是客服了我浮躁的内心,静下心来看了看前面的代码,并且理解了,这样可以继续看下去了

    之所以点击list3的时候12都做出了相应的变化,是因为当你单击list3的时候,也单击了其祖先列表

    • 事件冒泡--

    • 事件捕获--

    • W3C捕获以及冒泡事件流

    阻止冒泡

    function stopPropagation(eventObject)
    {
        eventObject=eventObject||getEventObject(eventObject);
        if (eventObject.stopPropagation)
        {
            eventObject.stopPropagation();
        }
        else
        {
            eventObject.cancelBubble=true;
        }
    }
    window['ADS']['stopPropagation']=stopPropagation;

    阻止事件

    function preventDefault(eventObject)
    {
        eventObject=eventObject||getEventObject(eventObject);
        if (eventObject.preventDefault)
        {
            eventObject.preventDefault();
        }
        else
        {
            eventObject.returnValue=false;
        }
    }
    
    window['ADS']['preventDefault']=preventDefault;

    二、注册事件

    • 嵌入式注册事件
    <a href="www.baidu.com" onclick="window.opent(this.href);return false;">http://baidu.com/</a>
    • 深入理解ADS.addEvent()方法
    function addEvent(obj,type,fn)
    {
        if(obj.attachEvent)
        {
            obj['e'+type+fn]=fn;
            obj[type+fn]=function(){obj['e'+type+fn](window.event);}
            obj.attachEvent('on'+type+obj[type+fn]);
        }
        else
            obj.addEventListner(type,fn,false);
    }
    • 传统事件注册
    window.onload=function()
    {
        var anchor=document.getElementById('example');
        anchor.onclick=function()
        {
            //单击事件时候执行代码
        }
    }

    Microsoft特有的事件模型

    function eventListener()
    {
        //响应单击事件的代码
    }
    
    window.attachEvent('onload',function(){
        var link = document.getElementById('example');
        //增加事件
        link.attachEvent('onclick',eventListener);
    
        //去除事件
        //link.detachEvent('onclick',eventListener);
    });
    • W3C DOM2事件模型
    //w3c事件注册
    function eventListener()
    {
        //响应单击事件的代码
    }
    window.addEventListener('load',function(W3CEvent))
    {
        var link = document.getElementById('example');
        link.addEventListener('click',eventListener,false);
    },false);
    
    //移除事件监听器
    link.removeEventListener('click',eventListener,false);
    • load事件

    无论那种事件注册方法,load事件会一直等到所有图像全部加载完之后才被调用,要解决这问题,我们要在ADS库中添加如下方法

    function addLoadEvent(loadEvent,waitForImage)
    {
        if (!isCompatible())
        {
            return false;
        }
        //如果等标记是ture则使用常规的添加事件的方法
        if (waitForImage)
        {
            return addEvent(window,'load',loadEvent);
        }
        //否则使用一下不同的方式包装loadEvent()方法
        //一边为this关键字指定正确的内容,同事确保事件不会被执行两次
        var init = function()
        {
            //如果这个函数已经被调用了,则返回
            if (argument.callee.done)
            {
                return;
            }
            //标记这个函数,以便检查他是否运行过
            arguments.callee.done=true;
            //在document的环境中运行载入事件
            loadEvent.apply(document,arguments);
        };
    
        //为DOMContentLoad事件注册事件侦听器
        if (document.addEventListener)
        {
            document.addEventListener("DOMContenLoaded",init , false);
        }
        //对于safari使用setInterval()函数检测document是否咱如完成
        if (/WebKit/i.test(navigator.userAgent))
        {
            var _timer=setInterval(function(){
                if (/loaded|complete/.test(document.readyState))
                {
                    clearInterval(_timer);
                    init();
                }
            },10);
        }
    
        //对于IE(使用条件注释),附加一个在载入过程最后执行的脚本。
        //并检测该脚本是否载入完成
        /*@cc_on*/
        /*if(@_win32)
        document.write("<script id=__ie_onload defer src=javascript:void(0)></script>");
        var script=document.getElementById("__ie_onload");
        script.onreadystateChange=function()
        {
            if (this.readyState=='complete')
            {
                init();
            }
        };
        /*@end @*/
        return true;
    
    }
    window['ADS']['addLoadEvent']=addLoadEvent;

    跨浏览器的事件属性和方法

    • W3C DOM2事件模型为Event对象

    定义了下列属性。

    bubbles:是否是冒泡事件;

    cancelable:是否可以被取消默认动作;

    currentTarget:是当前正在处理的事件侦听器所在的事件流中的DOM元素;

    target:是DOM文档中最早调用事件序列的目标对象(EventTarget对象的实例);

    timestamp:是一个DOMTimeStamp对象,确定子创建事件的纪元事件算起经过的毫秒数。但不一定在所有系统中都有效

    type:包含时间名称的字符串值

    eventPhase:当前事件侦听器出去事件流的那个阶段123~也可以用如下:

    function eventListener(W3CEvent)
    {
        switch (W3CEvent.eventPhase)
        {
        case  Event.CAPTURING:
            //如果处于捕获阶段要运行的代码
        break;
        case Event.AT_TARGET
            //如果当前目标对象要运行的代码
        break;
        case Event.BUBBLING_PHASE:
            //如果处于冒泡阶段要运行的代码
        break;
        }
    }

    W3C DOM2事件模型也定义了下列的Event对象方法
    initEvent(eventType,canBubble,cancelable):用于初始化通过document.createEvent('Event')方法创建的事件对象。

    preventDefalt():用于取消对象的默认动作

    stopPropagation()用于停止事件流的进一步执行,包括捕获阶段、目标对象和冒泡阶段。

    DOM2事件规范定义的MouseEvent对象:

    MouseEvent对象属性:altKey,ctrlKey,shiftKey,分别表示在鼠标事件发僧是否按住了键盘上的Alt,Ctrl,Shift键

    button ,button中会包含表示哪个鼠标键按下的一个整数值。鼠标山每个键与证书的对应关系:

    0表示鼠标的左键;1表示中(如果有)2表示右

    if (W3CEvent.button==0)
    {
        //左键的单机事件
    }
    //或者
    if (W3CEvent.button==MouseEvent.BUTTON_LEFT)
    {
        //左键单击的代码
    }

    还有clientX和clientY类似的还有screenX和screenY

    document.addEventListener('click',function(W3CEvent){
        alert('client:('+W3CEvent.clientX+','+W3CEvent.clientY+')');
    },false);

    处理诸多不兼容性问题

    • 访问事件的目标元素
    function getTarget(eventObject)
    {
        eventObject=eventObject||getEventObject(eventObject);
    
        //如果是W3C或者MSIE的模型
        var target=eventObject.target||eventObject.srcElement;
    
        //如果想Safari中一样是一个文本节点,重新将目标对象指定为父元素
        if (target.nodeType==ADS.node.TEXT_NODE)
        {
            target=node.parentNode;
        }
        return target;
    }
    
    window['ADS']['getTarget']=getTarget;

    通过这个方法,可以取得给定事件的目标:

    ADS.addEvent(window,'load',function(){
        function eventListener(W3CEvent)
        {
            //取得目标
            var target=ADS.getTarget(W3CEvent);
            //target现在引用的是一个适当的元素
            window.open(target.href);
        }
        var anchor = document.getElementById('example');
        addEvent(anchor,'click',eventListener);
    });
    • 确定单击了哪个鼠标键(下面代码直接copy源代码的。不高兴敲了)
    function getMouseButton(eventObject) {
        eventObject = eventObject || getEventObject(eventObject);
        // Initialize an object wit the appropriate properties
        //使用适当的属性初始化一个对象变量
        var buttons = {
            'left':false,
            'middle':false,
            'right':false
        };
        /*检查eventObject对象的toString()方法的值,W3C DOM对象有toString方法
        并且此时可方法的返回值应该是MouseEvent*/
        // Check the toString value of the eventObject
        // W3C Dom object have a toString method and in this case it
        // should be MouseEvent
        if(eventObject.toString && eventObject.toString().indexOf('MouseEvent') != -1) {
            // W3C Method
            switch(eventObject.button) {
                case 0: buttons.left = true; break;
                case 1: buttons.middle = true; break;
                case 2: buttons.right = true; break;
                default: break;
            }
        } else if(eventObject.button) {
            // MSIE method
            switch(eventObject.button) {
                case 1: buttons.left = true; break;
                case 2: buttons.right = true; break;
                case 3:
                    buttons.left = true;
                    buttons.right = true;
                break;
                case 4: buttons.middle = true; break;
                case 5:
                    buttons.left = true;
                    buttons.middle = true;
                break;
                case 6:
                    buttons.middle = true;
                    buttons.right = true;
                break;
                case 7:
                    buttons.left = true;
                    buttons.middle = true;
                    buttons.right = true;
                break;
                default: break;
            }
        } else {
            return false;
        }
        return buttons;
    
    }
    window['ADS']['getMouseButton'] = getMouseButton;

    处理鼠标的位置:

    function getPointerPositionInDocument(eventObject) {
        eventObject = eventObject || getEventObject(eventObject);
        var x = eventObject.pageX || (eventObject.clientX +
            (document.documentElement.scrollLeft || document.body.scrollLeft));
        var y= eventObject.pageY || (eventObject.clientY +
            (document.documentElement.scrollTop || document.body.scrollTop));
        //x and y now contain the coordinates of the mouse relative to the document origin
        return {'x':x,'y':y};
    }
    window['ADS']['getPointerPositionInDocument'] = getPointerPositionInDocument;
    • 访问键盘命令
    function getKeyPressed(eventObject) {
        eventObject = eventObject || getEventObject(eventObject);
        var code = eventObject.keyCode;
        var value = String.fromCharCode(code);
        return {'code':code,'value':value};
    }
    window['ADS']['getKeyPressed'] = getKeyPressed;

     

  • 相关阅读:
    滚轮事件
    键盘事件
    运动(学习)
    事件(没有尽头的待完善)
    js 盒子模型(没写完)
    Number 数字相关的方法, 强制 、隐式类型转换 、进制之间转换
    操作DOM 和 节点
    DOM
    Object 的一些静态方法 、 for-in 循环、Object.keys() 、Object.values()、Object.entries()
    删除字段
  • 原文地址:https://www.cnblogs.com/sunhan/p/3542392.html
Copyright © 2011-2022 走看看