2011-06-03 90 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); 

}); 
相关问题