2011-06-03 46 views
8

有點建築問題...如何將Javascript單例更改爲可以多次使用的東西?

我最初創建了一個Javascript單例,以容納在CMS系統的模板文件中操作照片庫模塊所需的方法。原始規範僅在頁面上調用此照片庫模塊的一個實例。 (下面的代碼實際上是對我實際編寫的內容的簡化。)

在發佈代碼後不久,即使規範要求調用此模塊的一個實例,該代碼也會崩潰,如果頁面有兩個模塊實例(即用戶通過CMS向頁面添加兩個照片畫廊)。現在,HTML標記是安全的,因爲我使用了類名,但是如何重構我的Javascript和jQuery事件偵聽器以便能夠處理多個模塊?您可以假設每個照片庫都有自己的JSON-P文件(或者如果您認爲可以使用一個JSON-P文件更優雅地處理它,您可以假定一個JSON-P文件)。

我認爲我原來的jQuery事件偵聽器可能必須轉換爲$ .delegate(),但我不知道該做什麼之後,以及如何做轉換我的單身。任何線索將不勝感激。如果你提供代碼,我更喜歡優化的可讀性。

我不是問這個問題,因爲我立即需要解決工作中的問題。我問這個問題是前瞻性的,想成爲一個更好的Javascript開發人員,因爲我期待未來遇到這個問題,並希望做好準備。

謝謝您的閱讀。

HTML

<div class="photoGalleryMod"> 
    <div class="photoGalleryImgBox"><img src="http://www.test.org/i/intro.jpg" alt="Intro Photo" /></div> 
    <div class="photoGalleryImgCap"><p>Caption</p></div> 
    <a href="#" class="photoGalleryPrevImgLnk"></a> 
    <a href="#" class="photoGalleryNextImgLnk"></a> 
</div> 

的JavaScript是外部靜態文件,使通過$ .getSCript一個JSON-P檔()的調用,通過CMS中創建。

使用Javascript/jQuery的

(function($) { 
    photoGalleryModule = { 
     json: '', 
     numSlidesInJson: '', 
     currentSlide: '', 
     updateSlide: function (arg_slidNum) { 
      /* Update the slide here */ 
     }, 
     init: function (arg_jsonObj) { 
      this.json = arg_jsonObj; 
      this.numSlidesInJson = this.json.photoGallerySlides.length; 
      this.currentSlide = 0; 
     } 
    }; 

    $(document).ready(function() { 
     $.getScript('./photogallery.json'); 

     $('.photoGalleryPrevImgLnk').live('click', function(event) { 
      photoGalleryModule.currentSlide = photoGalleryModule.currentSlide - 1; 
      photoGalleryModule.updateSlide(photoGalleryModule.currentSlide); 
      event.preventDefault(); 
     }); 

     $('.photoGalleryNextImgLnk').live('click', function(event) { 
      photoGalleryModule.currentSlide = photoGalleryModule.currentSlide + 1; 
      photoGalleryModule.updateSlide(photoGalleryModule.currentSlide); 
      event.preventDefault(); 
     }); 
    }); 
})(jQuery); 

照片gallery.json

photoGalleryModule.init(
{ 
    photoGallerySlides: 
     [ 
      { 
       type: 'intro', 
       pageTitle: 'Intro Photo', 
       imgUrl: 'http://www.test.org/i/intro.jpg', 
       imgAltAttr: 'Intro photo', 
       captionText: 'The intro photo', 
      }, 
      { 
       type: 'normal', 
       pageTitle: 'First Photo', 
       imgUrl: 'http://www.test.org/i/img1.jpg', 
       imgAltAttr: 'First photo', 
       captionText: 'the first photo', 
      }, 
      { 
       type: 'normal', 
       pageTitle: 'Second Photo', 
       imgUrl: 'http://www.test.org/i/img2.jpg', 
       imgAltAttr: 'Second photo', 
       captionText: 'the second photo', 
      } 
     ] 
}); 

回答

5

的內容,我認爲最簡單的方法是隻是把你的代碼放到一個插件。因此,對於下面的HTML:

<div id="photoGallery1"> 
    <div class="photoGalleryImgBox"></div> 
    <div class="photoGalleryImgCap"></div> 
    <a href="#" class="photoGalleryPrevImgLnk"></a> 
    <a href="#" class="photoGalleryNextImgLnk"></a> 
</div> 

<div id="photoGallery2"> 
    ... 
</div> 

<div id="photoGallery3"> 
    ... 
</div> 

您將創建$.fn.photoGallery,你在一個索引作爲參數傳遞插件:

$.fn.photoGallery = function (index) { 
    var $this = this, 
     module = { 
      json: '', 
      numSlidesInJson: '', 
      currentSlide: '', 
      updateSlide: function (arg_slidNum) { 
       /* Update the slide here */ 
      }, 
      init: function (arg_jsonObj) { 
       module.json = arg_jsonObj; 
       module.numSlidesInJson = module.json.photoGallerySlides.length; 
       module.currentSlide = 0; 
      } 
     }, 
     events = { 
      prev: function(e) { 
       module.currentSlide = module.currentSlide - 1; 
       module.updateSlide(module.currentSlide); 
       e.preventDefault(); 
      }, 
      next: function(e) { 
       module.currentSlide = module.currentSlide + 1; 
       module.updateSlide(module.currentSlide); 
       e.preventDefault(); 
      } 
     }; 

    $.getScript('./photogallery' + index + '.json'); 

    $this.find('.photoGalleryPrevImgLnk').live('click', events.prev); 
    $this.find('.photoGalleryNextImgLnk').live('click', events.next); 
}; 

,然後開始每家畫廊,像這樣:

$(document).ready(function(){ 
    $('#photoGallery1').photoGallery(1); 
    $('#photoGallery2').photoGallery(2); 
    $('#photoGallery3').photoGallery(3); 
}); 

如果你有文件photogallery1.jsonphotogallery2.jsonphotogallery3.json,每個文件都調用module.init({ ... });必要的對象t數據。

+0

感謝這個答案,mVChr。我將更多地閱讀jQuery插件。 – Stephen 2011-06-03 18:35:25

2

東西like this應該做的伎倆:(未經測試)

// jquery plugin: jquery.photogallery.js 
$.fn.photoGallery = (function($){ 
    var PhotoGalleryModule = function(el, opts){ 
     $.extend(this, opts); 
     this.el = $(el); 
     // if there are multiple on the page do not re-bind or re-init 
     if(!!this.el.data('photoGallery')) return el; 

     this.numSlidesInJson = this.json.photoGallerySlides.length; 
     this.bind(); 

    }; 
    PhotoGalleryModule.prototype = { 
     updateSlide: function (arg_slidNum) { 
      /* Update the slide here */ 
     }, 
     bind: function(){ 
      var self = this; 
      this.el.find('.photoGalleryPrevImgLnk') 
       .live('click', function(event) { 
       self.currentSlide = self.currentSlide - 1; 
       self.updateSlide(self.currentSlide); 
       event.preventDefault(); 
      }); 
      this.el.find('.photoGalleryNextImgLnk') 
       .live('click', function(event) { 
       self.currentSlide = self.currentSlide + 1; 
       self.updateSlide(self.currentSlide); 
       event.preventDefault(); 
      }); 
     } 
    }; 

    return function (opts) { 
     return this.each(function() { 
      $(this).data('photoGallery', 
       new PhotoGalleryModule(this, opts)); 
     }); 
    }; 
})(jQuery); 

// activate 
$(function(){ 
    var ready = function(){ 
     $('div.photoGalleryMod').photoGallery({ 
      // similar technique as below to load json 
      json: { photoGallerySlides: { /*...*/} }, 
      currentSlide: 0 
     }); 
    }; 
    // load script dynamically when needed 
    ('photoGallery' in $.fn) ? ready() : 
     $.getScript('/scripts/jquery.photogallery.js', ready); 

}); 
相關問題