莊周夢蝶

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

          傳統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);?


          主站蜘蛛池模板: 潞西市| 滦平县| 金门县| 新邵县| 浏阳市| 珲春市| 贺兰县| 来安县| 青海省| 宁武县| 彰武县| 梁山县| 日照市| 漳州市| 松滋市| 舒城县| 长葛市| 桂平市| 潼南县| 黄梅县| 旌德县| 克什克腾旗| 文化| 富顺县| 泗水县| 饶阳县| 旌德县| 山丹县| 潮州市| 芜湖市| 西和县| 嵊州市| 天水市| 四平市| 南岸区| 林周县| 辽宁省| 金溪县| 百色市| 咸丰县| 桃江县|