#javascript #jquery
#javascript #jquery
Вопрос:
Небольшой архитектурный вопрос…
Изначально я создал синглтон 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 является внешним статическим файлом и вызывает файл JSON-P через $.getScript(), созданный 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);
Содержимое файла photo-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',
}
]
});
Ответ №1:
Я думаю, что самый простой способ — это просто превратить ваш код в плагин. Итак, для следующего 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({ ... });
с необходимыми данными объекта.
Комментарии:
1. Спасибо за этот ответ, mVChr. Я пойду почитаю больше о плагинах jQuery.
Ответ №2:
Что-то подобное этому должно сработать: (непроверено)
// 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);
});