莊周夢蝶

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

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

          Posted on 2007-03-16 09:19 dennis 閱讀(1898) 評論(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);?


          主站蜘蛛池模板: 安图县| 曲沃县| 秦皇岛市| 襄城县| 台北县| 凤山县| 化德县| 昆明市| 乌拉特前旗| 山丹县| 白城市| 福鼎市| 仙游县| 合肥市| 平遥县| 梅河口市| 五原县| 武邑县| 金平| 理塘县| 德安县| 萍乡市| 左权县| 华蓥市| 通化市| 专栏| 会泽县| 沧源| 罗田县| 涞水县| 铜鼓县| 德格县| 左贡县| 西宁市| 德化县| 射洪县| 旬邑县| 临城县| 巴马| 陵水| 沧源|