我刚刚开始使用模块模式(感谢Christian Heilmann的原始教程)来组织我的jQuery,我遇到了一个奇怪的问题。请考虑以下javascript代码:
var Gallery = function(){
var $obj, $thumbs, $mainPic;
function init($e){
$obj = $e;
$thumbs = $obj.find('.thumbnail');
$mainPic = $obj.find('.main-pic');
$obj.find($thumbs).bind('click',updateMainPic);
};
function updateMainPic() {
$thumbs.removeClass('selected');
$thumb = $thumbs.filter(this);
$thumb.addClass('selected');
newPicUrl = $thumb.data('src');
$mainPic.attr('src',newPicUrl);
};
return {
init:init
}
}();
以下HTML中包含并使用了哪些内容:
<div id="gallery1">
<img src="" class="main-pic">
<ul>
<li class="thumbnail" data-src="photo1.jpg">Photo 1</li>
<li class="thumbnail" data-src="photo2.jpg">Photo 2</li>
<li class="thumbnail" data-src="photo3.jpg">Photo 3</li>
<li class="thumbnail" data-src="photo4.jpg">Photo 4</li>
</ul>
</div>
<script type="text/javascript">
Gallery.init($('#gallery1'));
</script>
<div id="gallery2">
<img src="" class="main-pic">
<ul>
<li class="thumbnail" data-src="photo1.jpg">Photo 1</li>
<li class="thumbnail" data-src="photo2.jpg">Photo 2</li>
<li class="thumbnail" data-src="photo3.jpg">Photo 3</li>
<li class="thumbnail" data-src="photo4.jpg">Photo 4</li>
</ul>
</div>
<script type="text/javascript">
Gallery.init($('#gallery2'));
</script>
我遇到的问题是点击#gallery1上的缩略图正在交换#gallery2的图像,但#gallery2正在按预期工作。似乎$ obj变量在实例之间共享,但我认为它仍然是作用于函数的私有实例。
非常感谢任何有关如何正确确定范围和工作的建议。
答案 0 :(得分:4)
问题是Gallery是单身人士。你调用第二个init的那一刻,你正在替换内部的$ obj变量。
在这种情况下我不会使用模块模式。如果你正在使用jQuery,那么编写一个jQuery插件(简单)或一个jQuery UI Widget(非常擅长维护状态)会更容易。
答案 1 :(得分:0)
我玩了你的场景一段时间,试图看看是否可以使用模块化模式;在绑定过程中看起来像是一个巨大的障碍。在updateMainPic()函数中确定“this”的范围变得非常困难。即使有像underscore.js这样强大的库,它们的_.bind()函数允许绑定到一个对象,也无法轻易克服这种情况。
就像Mike提到的那样,插件或小部件会使这项特殊任务变得微不足道:
$('li.thumbnail').bind('click', function() {
$(this).closest('div').find('.main-pic').attr('src', $(this).attr('data-src'));
$(this).addClass('selected');
$(this).siblings().removeClass('selected');
});
答案 2 :(得分:0)
模块模式更适合单身人士使用。每次调用init方法时,都要将$ obj变量重新分配给传递的$ e。所以简单地将$ obj移动到另外两个进入init并将三个参数传递给updateMainPic。如果您需要基于实例的指针,那么让您的单例返回一个原型函数,您可以创建实例并直接绑定到您的dom click事件。