如何将Javascript单例更改为可以多次使用的内容?
有点建筑问题 我最初创建了一个Javascript单例,以容纳在CMS系统的模板文件中操作照片库模块所需的方法。原始规范在一个页面上只调用了此照片库模块的一个实例。(下面的代码是对我实际编写的代码的粗略简化。) 在发布代码后不久,我突然意识到,即使规范要求该模块的一个实例,但如果一个页面有两个模块实例(即用户通过CMS向一个页面添加两个照片库),该代码也会崩溃。现在,HTML标记是安全的,因为我使用了类名,但是如何重新构造Javascript和jQuery事件监听器以能够处理多个模块呢?您可以假设每个照片库都有自己的JSON-P文件(或者,如果您认为一个JSON-P文件可以更优雅地处理一个JSON-P文件,那么您可以假设一个JSON-P文件) 我认为我最初的jQuery事件监听器可能必须转换为$.delegate(),但我不知道在这之后该怎么做,也不知道转换我的单例时该怎么做。任何线索将不胜感激。如果你提供代码,我更喜欢可读性而不是优化 我不是在问这个问题,因为我迫切需要为工作解决这个问题。我问这个问题是为了前瞻性的思考,也是为了成为一名更好的Javascript开发人员,因为我希望将来遇到这个问题,并做好准备 谢谢你的阅读 HTML如何将Javascript单例更改为可以多次使用的内容?,javascript,jquery,Javascript,Jquery,有点建筑问题 我最初创建了一个Javascript单例,以容纳在CMS系统的模板文件中操作照片库模块所需的方法。原始规范在一个页面上只调用了此照片库模块的一个实例。(下面的代码是对我实际编写的代码的粗略简化。) 在发布代码后不久,我突然意识到,即使规范要求该模块的一个实例,但如果一个页面有两个模块实例(即用户通过CMS向一个页面添加两个照片库),该代码也会崩溃。现在,HTML标记是安全的,因为我使用了类名,但是如何重新构造Javascript和jQuery事件监听器以能够处理多个模块呢?您可以假
<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>
照片库的内容.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',
}
]
});
我认为最简单的方法就是将代码转换成插件。因此,对于以下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>
然后启动每个库,如下所示:
$(document).ready(function(){
$('#photoGallery1').photoGallery(1);
$('#photoGallery2').photoGallery(2);
$('#photoGallery3').photoGallery(3);
});
其中有文件photogallery1.json
,photogallery2.json
和photogallery3.json
,每个文件调用module.init({…})使用必要的对象数据进行编码。应该有办法:(未测试)
谢谢你的回答,mVChr。我将阅读更多关于jQuery插件的内容。
$.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);
});
// 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);
});