[英]How to change a Javascript singleton to something that can be used multiple times?
A bit of an architectural question...有点建筑问题...
I originally created a Javascript singleton to house methods needed to operate a photo gallery module in a template file for a CMS system.我最初创建了一个 Javascript singleton 来容纳在 CMS 系统的模板文件中操作照片库模块所需的方法。 The original specification only called for one instance of this photo gallery module on a page.原始规范仅在页面上调用此照片库模块的一个实例。 (The code below is a gross simplification of what I actually wrote.) (下面的代码是对我实际编写的内容的粗略简化。)
Shortly after releasing the code, it dawned on me that even though the specification called for one instance of this module, this code would fall apart if a page had two instances of the module (ie the user adds two photo galleries to a page via the CMS).发布代码后不久,我突然意识到,即使规范要求此模块的一个实例,如果页面有两个模块实例(即用户通过CMS)。 Now, the HTML markup is safe, because I used class names, but how would I go about restructuring my Javascript and jQuery event listeners to be able to handle multiple modules? Now, the HTML markup is safe, because I used class names, but how would I go about restructuring my Javascript and jQuery event listeners to be able to handle multiple modules? You may assume that each photo gallery has its own JSON-P file (or you may assume a single JSON-P file if you think it can be handled more elegantly with one JSON-P file).您可以假设每个照片库都有自己的 JSON-P 文件(或者如果您认为使用一个 JSON-P 文件可以更优雅地处理它,您可以假设一个 JSON-P 文件)。
I think my original jQuery event listeners might have to be converted to $.delegate(), but I have no clue what to do after that and what to do about converting my singleton.我认为我原来的 jQuery 事件侦听器可能必须转换为 $.delegate(),但我不知道在那之后该怎么做以及如何转换我的 singleton。 Any leads would be appreciated.任何线索将不胜感激。 If you offer code, I prefer readability over optimization.如果你提供代码,我更喜欢可读性而不是优化。
I'm not asking this question, because I have an immediate need to solve the problem for work.我不是在问这个问题,因为我迫切需要解决工作中的问题。 I am asking this question to be forward-thinking and to be a better Javascript developer, because I am expecting to run into this problem in the future and want to be prepared.我问这个问题是有远见的,并成为一个更好的 Javascript 开发人员,因为我预计将来会遇到这个问题并希望做好准备。
Thank you for reading.感谢您的阅读。
HTML 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>
The Javascript is an external static file and makes a call to a JSON-P file via $.getSCript(), created by the CMS. Javascript 是一个外部 static 文件,并通过由 CMS 创建的 $.getSCript() 调用 JSON-P 文件。
Javascript/jQuery 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);
Contents of photo-gallery.json相册内容.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',
}
]
});
I think the easiest way is to just turn your code into a plugin.我认为最简单的方法就是把你的代码变成一个插件。 So for the following HTML:所以对于下面的 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>
You would create the plugin with $.fn.photoGallery
where you pass in an index as a parameter:您将使用$.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);
};
And then initiate each gallery like so:然后像这样启动每个画廊:
$(document).ready(function(){
$('#photoGallery1').photoGallery(1);
$('#photoGallery2').photoGallery(2);
$('#photoGallery3').photoGallery(3);
});
Where you have the files photogallery1.json
, photogallery2.json
and photogallery3.json
that each invoke module.init({... });
你有文件photogallery1.json
, photogallery2.json
和photogallery3.json
,每个调用module.init({... });
with the necessary object data.与必要的 object 数据。
Something like this should do the trick: (untested)像这样的东西应该可以解决问题:(未经测试)
// 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);
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.