javascript事件基础--自定义事件(封装)

设计弹框和遮罩层

<title>设计弹出对话框</title>
        <style>
            body{margin:0;padding: 0;}
            .dialog{
                width: 300px;height: 200px;
                /*margin: 0 auto;  这样子居中会被遮罩层覆盖,对话框的X按钮将不可用,改用position: fixed;*/ 
                position: fixed;left:50%;top: 50%;margin-top:-100px;margin-left: -150px;
                background-color: #f1f1f1;border:solid 1px #aaa;border-radius: 4px;
                overflow: hidden;box-shadow: 2px 2px 4px #CCCCCC;display: none;
                z-index: 30;
            }
            .dialog .title{
                padding: 6px;
                font-size: 16px;font-weight: bold;color:#fff;background-color: #404040;
            }
            .dialog .close{
                float:right;width: 20px;height: 20px;
                font-size:20px;color:#fff;cursor: pointer;
            }
            .pageCover{
                position: absolute;width:100%;height: 100%;
                background-color: #666;opacity: 0.1;display: none;
                z-index: 10;
            }
        </style>
    </head>
    <body>
         <div id="pageCover" class="pageCover"></div>
         
         <input type="button" value="打开对话框" οnclick="openDialog();"/>
         <div id="dlgTest" class="dialog">
             <span class="close">&times;</span>
             <div class="title">
                 对话宽标题
             </div>
             <div class="content">
                 对话框内容
             </div>
         </div>
         <script type="text/javascript">
             //1.函数写法
//              var odig=document.getElementById("dlgTest");
//              var cdig=document.getElementsByClassName("close")[0];
//              function  openDialog(){
//                  odig.style.display="block";
//              }
//                  cdig.οnclick=function(){
//                  odig.style.display="none";
//              }
            //2.对象写法
            function Dialog(id){//定义对话框类型对象
                this.id=id;
                var that=this;
                document.getElementById(id).children[0].οnclick=function(){
                    that.close();
                }
            }
            Dialog.prototype.show=function(){
                var dlg=document.getElementById(this.id);
                dlg.style.display="block";
                dlg=null;//清空引用,避免生产闭包
            }
            
           Dialog.prototype.close=function(){
//          document.getElementById("pageCover").style.display="none";  不能再这写这句代码
//因为在定义Dialog时并不知道遮罩层的存在,对话框和遮罩没有耦合关系,如果把关闭遮罩的逻辑写在Dialog的close方法内,
//那么会造成Dialog依赖于遮罩,如果页面没有遮罩时, Dialog就会出错(它的close方法中找不到遮罩,自然报错)
             
                var dlg=document.getElementById(this.id);
                dlg.style.display="none";
                dlg=null;
           }
           function openDialog(){
               document.getElementById("pageCover").style.display="block";

               var dlg=new Dialog("dlgTest");
               dlg.show();
           }
         </script>
    </body>

定义时间雏形:(那么怎么关闭遮罩层?) 

重写对话框类型对象

function Dialog(id){//定义对话框类型对象
                this.id=id;

             this.close_handler=null;//增加一个句柄性质的本地属性,默认为空
                var that=this;
                document.getElementById(id).children[0].onclick=function(){
                                 that.close();

                   //若果句柄的值为函数,则调用,实现       自定义事件函数  异步    触发

                               if(typeof that.close_handler=="funciton"){

                                   this.close_handler();

                                  }
                }
            }

//重写打开对话框的方法

 function openDialog(){
               document.getElementById("pageCover").style.display="block";
               var dlg=new Dialog("dlgTest");
               dlg.show();
               dlg.close_handler=function(){//注册事件,为句柄(本地属性)传递一个事件处理函数
                   document.getElementById("pageCover").style.display="none";
               }

           }

在openDialog方法中,创建Dialog对象后为句柄赋值,传递一个隐藏遮罩的方法,这样在关闭Dialog时就隐藏了遮罩,同时没有造成两个组件之间耦合

自定义事件:即先绑定事件处理程序,然后在原生事件处理函数中调用,以实现触发的过程。DOM对象的事件,如button的click事件,也是类似原理

设计事件触发模型;

//使用观察者模式实现事件监听,自定义事件类型
           
           function EventTarget(){
               this.handlers={};//初始本地句柄为空
           }
           
           //扩展自定义事件类型的原型
           EventTarget.prototype={
               constructor:EventTarget,//修复EventTarget构造器本身
               addHandler:function(type,handler){//注册事件:type表示事件类型  handler表示事件处理函数
                   if(typeof this.handlers[type]=='undefined'){//如果没有注册指定类型事件,则初始化为空数组
                       this.handlers[type]=new Array();
                   }
                   this.handlers[type].push(handler);//把当前事件处理函数推入到当前事件类型句柄队列的尾部
               },
               removeHandler:function(type,handler){//销毁事件:type表示事件类型  handler表示事件处理函数
                   if(this.handlers[type] instanceof Array){
                       var handlers=this.handlers[type];
                       for(var i=0,len=handlers.length;i<len;i++){
                           if(handlers[i]==handler){//若果存在指定的事件处理函数,则删除该处理函数,然后跳出循环
                               handlers.splice(i,1);
                               break;
                           }
                       }
                   }
               },
               trigger:function(event){//触发事件
                   if(!event.target){//检测事件触发对象,若果不存在,则指向当前调用对象
                       event.target=this;
                   }
                   if(this.handlers[event.type] instanceof Array){
                       var handlers=this.handlers[event.type];
                       for(var i=0,len=handlers.length;i<len;i++){
                           handlers[i](event);//逐一调用队列中每个事件处理函数,并把参数event传递给它
                       }
                   }
               }
           }
           
           //测试自定义事件的添加和触发过程
           function onClose(event){//自定义事件处理函数
               alert('message'+event.Message);
           }
           var  target=new EventTarget();//实例化自定义事件类型
           target.addHandler('close',onClose);
           var event={//创建事件对象,传递事件类型,以及额外信息
               type:'close',
               message:'Page Cover closed!'
           };
           target.trigger(event);

 

//寄生式组合继承,javas最佳继承方式,解决  没有共同性的弊端
           function extend(subType,superType){
                 var prototype=Object(superType.prototype);
                 prototype.constructor=subType;
                 subType.prototype=prototype;     
           }

应用事件模型:优化后的总体代码

<head>
        <meta charset="UTF-8">
        <title>设计弹出对话框</title>
        <style>
            body{margin:0;padding: 0;}
            .dialog{
                width: 300px;height: 200px;
                /*margin: 0 auto;  这样子居中会被遮罩层覆盖,对话框的X按钮将不可用,改用position: fixed;*/ 
                position: fixed;left:50%;top: 50%;margin-top:-100px;margin-left: -150px;
                background-color: #f1f1f1;border:solid 1px #aaa;border-radius: 4px;
                overflow: hidden;box-shadow: 2px 2px 4px #CCCCCC;display: none;
                z-index: 30;
            }
            .dialog .title{
                padding: 6px;
                font-size: 16px;font-weight: bold;color:#fff;background-color: #404040;
            }
            .dialog .close{
                float:right;width: 20px;height: 20px;
                font-size:20px;color:#fff;cursor: pointer;
            }
            .pageCover{
                position: absolute;width:100%;height: 100%;
                background-color: #666;opacity: 0.1;display: none;
                z-index: 10;
            }
        </style>
    </head>
    <body>
         <div id="pageCover" class="pageCover"></div>
         
         <input type="button" value="打开对话框" οnclick="openDialog();"/>
         <div id="dlgTest" class="dialog">
             <span class="close">&times;</span>
             <div class="title">
                 对话宽标题
             </div>
             <div class="content">
                 对话框内容
             </div>
         </div>

<script>

 function EventTarget(){
               this.handlers={};//初始本地句柄为空
           }
           
           //扩展自定义事件类型的原型
           EventTarget.prototype={
               constructor:EventTarget,//修复EventTarget构造器本身
               addHandler:function(type,handler){//注册事件:type表示事件类型  handler表示事件处理函数
                   if(typeof this.handlers[type]=='undefined'){//如果没有注册指定类型事件,则初始化为空数组
                       this.handlers[type]=new Array();
                   }
                   this.handlers[type].push(handler);//把当前事件处理函数推入到当前事件类型句柄队列的尾部
               },
               removeHandler:function(type,handler){//销毁事件:type表示事件类型  handler表示事件处理函数
                   if(this.handlers[type] instanceof Array){
                       var handlers=this.handlers[type];
                       for(var i=0,len=handlers.length;i<len;i++){
                           if(handlers[i]==handler){//若果存在指定的事件处理函数,则删除该处理函数,然后跳出循环
                               handlers.splice(i,1);
                               break;
                           }
                       }
                   }
               },
               trigger:function(event){//触发事件
                   if(!event.target){//检测事件触发对象,若果不存在,则指向当前调用对象
                       event.target=this;
                   }
                   if(this.handlers[event.type] instanceof Array){
                       var handlers=this.handlers[event.type];
                       for(var i=0,len=handlers.length;i<len;i++){
                           handlers[i](event);//逐一调用队列中每个事件处理函数,并把参数event传递给它
                       }
                   }
               }
           }
         
           //寄生式组合继承,javas最佳继承方式,解决  没有共同性的弊端
           function extend(subType,superType){
                 var prototype=Object(superType.prototype);
                 prototype.constructor=subType;
                 subType.prototype=prototype;     
           }
           
           //定义对话框类型
           function Dialog(id){
                 EventTarget.call(this);//动态调用EventTarget类型函数,继承它的本地成员
                 this.id=id;
                 var that=this;
                 document.getElementById(id).children[0].οnclick=function(){
                    that.close();
                    }
           }
           //继承EventTarget类型原型属性
           extend(Dialog,EventTarget);
           
            Dialog.prototype.show=function(){
                var dlg=document.getElementById(this.id);
                dlg.style.display="block";
                dlg=null;//清空引用,避免生产闭包
            }
         
           Dialog.prototype.close=function(){
               var dlg=document.getElementById(this.id);
                dlg.style.display="none";
                dlg=null;
                
                this.trigger({type:'close'})
           }
           function openDialog(){
               document.getElementById("pageCover").style.display="block";
               var dlg=new Dialog("dlgTest");
               dlg.show();
               dlg.addHandler('close',function(){//为当前实例注册close事件,并传递事件函数
                   document.getElementById("pageCover").style.display="none";
               })
           }
           
         </script>

这样用户也可以在打开dialog时,显示遮罩写成类似关闭事件的方式。当代码中存在多个部分,在特定时刻相互交互的情况下,自定义事件就非常有用

如果每个对象都有其他对象的引用,那么整个代码高度耦合,对象改动会影响其他对象,维护起来就困难重重,自定义事件能够解耦,功能隔绝,这样对象之间就可以实现高度聚合

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值