莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          傳統javascript事件模型實現觀察者模式

          Posted on 2007-03-16 09:19 dennis 閱讀(1901) 評論(0)  編輯  收藏 所屬分類: web開發
          ??? 在W3C新的事件模型框架中,IE和Mozilla都實現了相應的版本,IE的是attachEvent和detachEvent來實現元素事件的添加和刪除,而Mozilla則是標準的addEventListener和 removeEventListener。在傳統的javascript事件模型中,我們沒辦法為一個頁面元素注冊多個事件,只有靠自己來實現觀察者模式。代碼來自《ajax in action》,我添加了注釋
          //命名空間
          var?jsEvent?=?new?Array();

          //構造函數
          jsEvent.EventRouter?=?function(el,eventType){
          ?
          //內部維護一個事件列表
          ?this.lsnrs?=?new?Array();
          ?
          this.el?=?el;
          ?el.eventRouter?
          =?this;
          ?
          //注冊回調函數
          ?el[eventType]?=?jsEvent.EventRouter.callback;
          };

          //添加事件
          jsEvent.EventRouter.prototype.addListener?=?function(lsnr){
          ?
          this.lsnrs.append(lsnr,true);?
          }?;

          //移除事件
          jsEvent.EventRouter.prototype.removeListener=
          function(lsnr){?
          this.lsnrs.remove(lsnr);?
          };?

          //通知所有事件
          jsEvent.EventRouter.prototype.notify?=?function(e){
          ?
          var?lsnrs?=?this.lsnrs;
          ?
          for(var?i=0;i<lsnrs.length;i++){
          ??
          var?lsnr?=?lsnrs[i];
          ??lsnr.call(
          this,e);
          ?}
          };
          //回調函數調用notify
          jsEvent.EventRouter.callback=function(event){
          ?
          var?e?=?event?||?window.event;
          ?
          var?router?=?this.eventRouter;
          ?router.notify(e);
          };

          Array.prototype.append?
          =?function(obj,nodup){
          ?
          if(nodup){?
          ??
          this[this.length]=obj;
          ?}
          };
          Array.prototype.remove?
          =?function(o)
          {
          ???
          var?i?=?this.indexOf(o);
          ???
          if?(i>-1)
          ??{
          ????
          this.splice(i,1);
          ???}
          ?????
          return?(i>-1);
          ???}??
          };?

          這里比較巧妙的就是
          ?el.eventRouter?=?this;
          //注冊回調函數
          ?el[eventType]?=?jsEvent.EventRouter.callback;

          首先給el元素添加屬性
          eventRouter是當前的EventRouter對象,然后,比如eventType假設為onclick,el是一個button元素,那么這里就是el[onclick]=jsEvent.EventRouter.callback;相當于el.onclick=jsEvent.EventRouter.callback;
          而請注意這個回調函數
          callback將首先得到元素的eventRouter對象,再調用此對象的notify方法觸發所有注冊的事件。

          再請注意notify函數里面這一行:
          ?lsnr.call(this,e);

          我們把event對象傳入此函數作參,而
          var?e?=?event?||?window.event;那么所有事件函數的第一個參數都將是event對象,避免了IE需要通過window.event得到的事件對象的瀏覽器不一致行為。

          使用此對象方式:
           var?mat=document.getElementById('mousemat');
            cursor
          =document.getElementById('cursor');
            
          var?mouseRouter=new?jsEvent.EventRouter(mat,"onmousemove");
            mouseRouter.addListener(writeStatus);
            mouseRouter.addListener(drawThumbnail);?


          主站蜘蛛池模板: 河源市| 闽清县| 沈丘县| 崇信县| 伊宁市| 西昌市| 凉山| 金坛市| 班玛县| 阿拉善右旗| 安丘市| 蓝山县| 陆川县| 普格县| 华亭县| 泸西县| 和平县| 万安县| 兴隆县| 尼木县| 五华县| 锡林浩特市| 太康县| 报价| 攀枝花市| 瑞金市| 抚顺县| 崇信县| 德惠市| 咸阳市| 武平县| 勐海县| 临漳县| 双牌县| 绿春县| 卓尼县| 柏乡县| 繁峙县| 金坛市| 清徐县| 铁岭县|