• js 高级应用 自定义事件


    Javascript与浏览器交互的途径主要是事件的形式。事件是一种观察者的设计模式,对象可以发布时间,然后其它对象可以观察该对象,等待这些时刻到来并通过运行代码来响应。

    观察者模式主要由主体和观察者组成。主体负责发布事件,同时观察者通过订阅这些事件来观察该主体。该模式的一个关键概念是主体并不知道观察者的任何事情,也就是说它可以独自存在并正常运行即使观察者不存在。从另一方面来讲观察者知道主体并能注册事件的回调函数(事件处理程序)。

    事件是与DOM交互的最常用的方式,但也可以用于非DOM的代码中—通过实现自定义事件。自定义事件的机制其实就是创建一个可以管理事件的对象。让其他对象监听那些事件。

     1 function EventTarget(){
     2     this.handles={};
     3 }
     4 EventTarget.prototype = {
     5     constructor: EventTarget,
     6     addHandler:function(type,fn){
     7         if(!(this.handles[type] instanceof Array)){
     8             this.handles[type] = [];
     9         }
    10         this.handles[type].push(fn);
    11     },
    12     fire:function(event){
    13         if(!event.target){
    14             event.target = this;
    15         }
    16         if(this.handles[event.type] instanceof Array){
    17             var handles = this.handles[event.type];
    18             for(var i=0,len=handles.length;i<len;i++){
    19                 handles[i](event);
    20             }
    21         }
    22     },
    23     removeHandler:function(type,fn){
    24         if (this.handles[type] instanceof Array) {
    25             var handles = this.handles[type];
    26             for (var i =0,len = handles.length;i<len;i++) {
    27                 if(handles[i] == fn){
    28                     break;
    29                 }
    30             };
    31             handles.splice(i,1);
    32         };
    33     }
    34 }

    EventTarget有一个单独的属性,用于储存事件处理程序,三个方法中,addHandler用于添加事件处理程序,将事件添加到相应的事件型号的数组下,用push添加到数组的最后。removeHandler用于移除相应的事件。fire用于触发相应事件类型下的所有事件,通过for的形式循环触发。

    要使用这个自定义事件类型,可以通过以下这个方式。

     1 function Person(name){
     2     this.name = name;
     3     this.etarget = new EventTarget();
     4 }
     5 Person.prototype = {
     6     constructor:Person,
     7     say:function(message){
     8         this.etarget.fire({type:'message',target:this,message:message});
     9     },
    10     addMess:this.addMess = function(type,fn){
    11         this.etarget.addHandler(type,fn);
    12     }
    13 }

    这样就可以做到事件监听机制的使用了。在这里,一旦调用say方法,便触发了事件,它包含了事件的细节。同时在其中fire不是公开调用的,这段代码可以按以下方式使用。

    1 var person = new Person('Tom');
    2 person.addMess('message',function(event){
    3     console.log(event.target.name+'says:'+event.message);
    4 })
    5 person.say('hello!!!');

     EXAMPLE:拖放

    拖放是一种常见的用户界面模式,在HTML5中也有类似的API实现了该功能,在这里我们会用javascript和html来实现这个功能。

    拖放的核心函数调用就是mousemove了,通过鼠标移动不断触发,并不断调整位置,实现拖动的连续性。

     1  var Dragdrop = (function(){
     2      var dragging = null;
     3      dragHandler = function(event){
     4          var event = event||window.event,
     5          target = event.target ||event.srcElement;
     6          switch(event.type){
     7              case 'mousedown':
     8                  if(target.className.indexOf('draggable') > -1){
     9                      dragging = target;               
    10                  }
    11                  break;
    12              case 'mousemove':
    13                  if(dragging != null){
    14                      dragging.style.left = event.pageX+'px';
    15                      dragging.style.top = event.pageY+'px';   
    16                  }
    17                  break;
    18              case 'mouseup':
    19                  dragging = null;           
    20                  break;
    21          }
    22      };
    23      return {enable : function(){
    24          document.addEventListener('mouseup',dragHandler,false);
    25          document.addEventListener('mousemove',dragHandler,false);
    26          document.addEventListener('mousedown',dragHandler,false);
    27      },
    28      disable: function(){
    29          document.removeEventListener('mouseup',dragHandler,false);
    30          document.removeEventListener('mousemove',dragHandler,false);
    31          document.removeEventListener('mousedown',dragHandler,false);
    32      }}
    33  })();

    现在还不能实现真正的交互,因为我们无法知道到底什么时候开始拖动,拖动结束。这时就可以用自定义事件来指示这个事件的发生。实现方式主要是先创建一个新的EventTarget的对象,然后添加enable和disable方法,最后返回这个对象:

     1 var Dragdrop = (function(){
     2     var dragEvent = new EventTarget(),
     3     dragging = null;
     4     dragHandler = function(event){
     5         var event = event||window.event,
     6         target = event.target ||event.srcElement;
     7         switch(event.type){
     8             case 'mousedown':
     9                 if(target.className.indexOf('draggable') > -1){
    10                     dragging = target;
    11                     dragEvent.fire({target:dragging,type:'dragstart'});
    12                 }
    13                 break;
    14             case 'mousemove':
    15                 if(dragging != null){
    16                     dragging.style.left = event.pageX+'px';
    17                     dragging.style.top = event.pageY+'px';
    18                     dragEvent.fire({target:dragging,type:'dragmove',pos:{left:event.pageX,top:event.pageY}});
    19                 }
    20                 break;
    21             case 'mouseup':
    22                 dragging = null;
    23                 dragEvent.fire({target:dragging,type:'dragstop'});
    24                 break;
    25         }
    26     };
    27     dragEvent.enable = function(){
    28         document.addEventListener('mouseup',dragHandler,false);
    29         document.addEventListener('mousemove',dragHandler,false);
    30         document.addEventListener('mousedown',dragHandler,false);
    31     };
    32     dragEvent.disable = function(){
    33         document.removeEventListener('mouseup',dragHandler,false);
    34         document.removeEventListener('mousemove',dragHandler,false);
    35         document.removeEventListener('mousedown',dragHandler,false);
    36     };
    37     return dragEvent;
    38 })();

    在对代码的主要改动处都以特殊的字体标出来了,这些改动使得Dragdrop对象支持了事件,使用方式如下:

    1 Dragdrop.addHandler('dragstart',function(event){
    2     console.log('drag start!');
    3 });
    4 Dragdrop.addHandler('dragmove',function(event){
    5     console.log('dragmove,pos:'+event.pos.left+':'+event.pos.top);
    6 });
    7 Dragdrop.addHandler('dragstop',function(event){
    8     console.log('dragstop');
    9 });

    这样就死的Dragdrop对象更加健壮了,就可以处理一下复杂的拖放事件了。

    所有代码集合如下:

    <html>
    <head>
        <script type="text/javascript">
            function EventTarget(){
                this.handles={};
            }
            EventTarget.prototype = {
                constructor: EventTarget,
                addHandler:function(type,fn){
                    if(!(this.handles[type] instanceof Array)){
                        this.handles[type] = [];
                    }
                    this.handles[type].push(fn);
                },
                fire:function(event){
                    if(!event.target){
                        event.target = this;
                    }
                    if(this.handles[event.type] instanceof Array){
                        var handles = this.handles[event.type];
                        for(var i=0,len=handles.length;i<len;i++){
                            handles[i](event);
                        }
                    }
                },
                removeHandler:function(type,fn){
                    if (this.handles[type] instanceof Array) {
                        var handles = this.handles[type];
                        for (var i =0,len = handles.length;i<len;i++) {
                            if(handles[i] == fn){
                                break;
                            }
                        };
                        handles.splice(i,1);
                    };
                }
            }
            var Dragdrop = (function(){
                var dragEvent = new EventTarget(),
                dragging = null;
                dragHandler = function(event){
                    var event = event||window.event,
                    target = event.target ||event.srcElement;
                    switch(event.type){
                        case 'mousedown':
                            if(target.className.indexOf('draggable') > -1){
                                dragging = target;
                                dragEvent.fire({target:dragging,type:'dragstart'});
                            }
                            break;
                        case 'mousemove':
                            if(dragging != null){
                                dragging.style.left = event.pageX+'px';
                                dragging.style.top = event.pageY+'px';
                                dragEvent.fire({target:dragging,type:'dragmove',pos:{left:event.pageX,top:event.pageY}});
                            }
                            break;
                        case 'mouseup':
                            dragging = null;
                            dragEvent.fire({target:dragging,type:'dragstop'});
                            break;
                    }
                };
                dragEvent.enable = function(){
                    document.addEventListener('mouseup',dragHandler,false);
                    document.addEventListener('mousemove',dragHandler,false);
                    document.addEventListener('mousedown',dragHandler,false);
                };
                dragEvent.disable = function(){
                    document.removeEventListener('mouseup',dragHandler,false);
                    document.removeEventListener('mousemove',dragHandler,false);
                    document.removeEventListener('mousedown',dragHandler,false);
                };
                return dragEvent;
            })();
            /*function Person(name){
                this.name = name;
                this.etarget = new EventTarget();
            }
            Person.prototype = {
                constructor:Person,
                say:function(message){
                    this.etarget.fire({type:'message',target:this,message:message});
                },
                addMess:this.addMess = function(type,fn){
                    this.etarget.addHandler(type,fn);
                }
            }
            var person = new Person('Tom');
            person.addMess('message',function(event){
                console.log(event.target.name+'says:'+event.message);
            })
            person.say('hello!!!');*/
            Dragdrop.addHandler('dragstart',function(event){
                console.log('drag start!');
            });
            Dragdrop.addHandler('dragmove',function(event){
                console.log('dragmove,pos:'+event.pos.left+':'+event.pos.top);
            });
            Dragdrop.addHandler('dragstop',function(event){
                console.log('dragstop');
            });
        </script>
    </head>
    <body>
        <div class="draggable" style="position:absolute;100px;height:100px;background:silver"></div>
    </body>
    </html>
    View Code
  • 相关阅读:
    django变量使用-在模板中使用视图函数中的变量
    django创建app、在视图函数及url中使用参数、url命名、通过redirect实现网页路径跳转
    第一个django项目-通过命令行和pycharm两种方式
    python安装虚拟环境virtualenvwrapper
    装饰器案例由来例子
    转发:python 装饰器--这篇文章讲的通俗易懂
    JVM调优之jstack找出最耗cpu的线程并定位代码
    mysql视图定义、原理、创建、使用
    列表生成 加1四种方法
    【good】在CentOS 6.x上安装GlusterFS
  • 原文地址:https://www.cnblogs.com/cyITtech/p/3566897.html
Copyright © 2020-2023  润新知