如何将Javascript单例更改为可以多次使用的单例
How to change a Javascript singleton to something that can be used multiple times?
一个架构问题。。。
我最初创建了一个Javascript单例来容纳在CMS系统的模板文件中操作照片库模块所需的方法。原始规范在一个页面上只调用了此照片库模块的一个实例。(下面的代码是对我实际写的内容的粗略简化。)
在发布代码后不久,我突然意识到,尽管规范要求该模块的一个实例,但如果一个页面有两个模块实例(即用户通过CMS向一个页面添加两个照片库),该代码也会崩溃。现在,HTML标记是安全的,因为我使用了类名,但我该如何重新构造Javascript和jQuery事件侦听器以能够处理多个模块呢?您可以假设每个照片库都有自己的JSON-P文件(或者,如果您认为使用一个JSON-P文件可以更优雅地处理它,则您可以假设使用一个单独的JSON-SP文件)。
我认为我最初的jQuery事件侦听器可能必须转换为$.delete(),但我不知道在那之后该怎么办,也不知道如何转换我的singleton。任何线索都将不胜感激。如果你提供代码,我更喜欢可读性而不是优化。
我没有问这个问题,因为我迫切需要为工作解决这个问题。我提出这个问题是为了前瞻性思考,成为一名更好的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是一个外部静态文件,通过CMS创建的$.getSCript()调用JSON-p文件。
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);
照片库.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>
您将使用$.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.json
、photogallery2.json
和photogallery3.json
,它们分别用必要的对象数据调用module.init({ ... });
。
像这样的东西应该可以做到:(未测试)
// 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);
});
- 创建命名空间 Javascript 单例类的对象
- Javascript 单例模式
- 为什么这个javascript单例方法有效
- JavaScript 对象的单例行为
- Javascript 文字对象和单例模式
- JavaScript 中的单例实例范围混淆
- Javascript 单例继承
- Javascript/NodeJS是创建单例对象的最佳方式
- JavaScript,如何在使用单例时保持适当的封装
- 带构造函数的语义JavaScript单例
- 在javascript中还有其他实现单例模式的方法吗?
- 如何在javascript中基于参数创建对象的单例实例
- Javascript单例函数不工作
- JavaScript单例模式-差异
- _.bindAll()用于JavaScript单例方法
- Angularjs / javascript如何更新工厂创建的单例
- 如何保存javascript "this"单例模式中的上下文
- Javascript中的单例和原型
- Javascript弹出窗口作为一个单例
- 如何将我的模块单例 JavaScript 转换为支持实例