我写了以下jquery插件。我想要做的是,当用户点击链接时,进行相关的div显示:基于数据属性的块。但是这个插件不起作用。在过去的两天里,我试图解决这个问题。但我失败了。
我的HTML
<div class="container1">
<a href="#" class="link1" data-link="a">asd</a>
<div class="window1" data-window="a">
asd
</div>
</div>
<hr>
<div class="container2">
<a href="#" class="link2" data-link="b">asdf1</a>
<a href="#" class="link2" data-link="c">asdf2</a>
<a href="#" class="link2" data-link="d">asdf3</a>
<div class="window2" data-window="b">
asdf1
</div>
<div class="window2" data-window="c">
asdf2
</div>
<div class="window2" data-window="d">
asdf3
</div>
</div>
<script src="jquery-1.11.0.min.js"></script>
<script src="script.js"></script>
<script>
$('.container1').myPlugin({
link: $('.link1'),
container : $('.window1')
});
$('.container2').myPlugin({
link: $('.link2'),
container : $('.window2')
});
</script>
插件
(function ($, window, document, undefind) {
MyPlugin = {
init : function (options, element) {
$.fn.myPlugin.config = $.extend({}, $.fn.myPlugin.config, options);
var link = $.fn.myPlugin.config.link;
link.on('click', this.secondFunc);
},
secondFunc : function () {
var dataLinkId = $(this).data('link'),
container = $($.fn.myPlugin.config).filter('[data-section="' + dataLinkId + '"]');
container.show();
}
};
$.fn.myPlugin = function(options) {
return this.each(function () {
var rezG = Object.create(MyPlugin);
rezG.init(options, this);
});
};
$.fn.myPlugin.config = {
link: $('.link'),
container : $('.container')
};
})(jQuery, window, document);
CSS
.window1, .window2 {
display: none;
}
答案 0 :(得分:2)
您需要使用var
来确保您的变量都是本地变量而不是全局变量。
var MyPlugin = {
// ...
};
此外,在init
函数中,您正在执行此操作:
$.fn.myPlugin.config = $.extend({}, $.fn.myPlugin.config, options);
这是覆盖 $.fn.myPlugin.config
,这是默认选项。这意味着调用myPlugin()
的所有元素将使用相同的配置。您只需要在一个实例上设置配置。
this.config = $.extend({}, $.fn.myPlugin.config, options);
您的secondFunc
没有对象(rezG
)实例的引用,因此无法访问配置。您需要将其传递给secondFunc()
。一种方法是使用闭包来捕获实例。
secondFunc: function (rezG) {
return function(){
var dataLinkId = $(this).data('link'),
container = $(rezG.config.container).filter(function(){
return $(this).data('window') == dataLinkId;
});
container.show();
};
}
然后你这样绑定它:
link.on('click', this.secondFunc(this));
请注意,在secondFunc
中,您需要使用config.container
(不仅仅是config
作为对象),而且您的属性也是data-window
,而不是{{1 }}
答案 1 :(得分:1)
您的插件可以像
一样简单(function ($, window, document, undefind) {
$.fn.myPlugin = function(options) {
// When $(stuff).myPlugin(...) is called
// this keyword inside of myPlugin function is referencing a set
// of elements plugin was called upon
// e.g. for call like $('.container1').myPlugin();
// this keyword will reference all elements selected by
// $('.container1') not jquery wrapped,
// in general it can be a any number.
return this.each(function pluginImplementation () {
// Here we iterate over the set, and for each element in the set
// we do some pretty standard click
var container = $(this);
// I use 'click.myPlugin' event instead just 'click' ale to later on
// do $(..).off('click.myPlugin') to remove only handlers that were
// attached by plugin (a good practice)
container.on('click.myPlugin', options.linkSelector, function(){
var dataLinkId = $(this).data('link');
container.find('[data-window="' + dataLinkId + '"]').toggle();
})
});
};
})(jQuery, window, document);
请参阅jsfiddle
然而,上面的代码可能会在每次迭代时创建一个问题luginImplementation ()
函数,如果该函数的主体更复杂,那将是一团糟。这就是为什么最好在外面创建pluginImplementation ()
。
(function ($, window, document, undefind) {
// Notice that pluginImplementation () now accepts parameters
// They make it possible for pluginImplementation to know which
// elements it's working with
function pluginImplementation (container, options) {
container.on('click.myPlugin', options.linkSelector, function(){
var dataLinkId = $(this).data('link');
container.find('[data-window="' + dataLinkId + '"]').toggle();
})
}
$.fn.myPlugin = function(options) {
return this.each(function () {
pluginImplementation($(this), options);
});
};
})(jQuery, window, document);
这种分离可能不够好。你可能希望你的插件更多OOP而不是。所以你可以像这样去所有的OOPy:
(function ($, window, document, undefind) {
// For that purpose we create a class
// That describes behavior that our plugin provides
//
function MyPlugin(container, options) {
this.container = container;
this.options = options;
// To the topic of maintainability
// This could be parametrised as an option at plugin instantiation
this.eventName = 'click.myPlugin';
}
MyPlugin.prototype.attachClickHandlers = function() {
var self = this;
// This gets a little messy with all the thises vs selfs and a
// noname function wrapping the handler.
// The point is to preserve this keyword reference
// inside of clickHandler method.
// If I would have just self.clickHandler as a handler there
// this keyword inside of self.clickHandler would reference to
// whatever $(...).on binds handlers to i.e. triggering element.
// I need this keyword inside of self.clickHandler to point to
// "current" instance of MyPlugin, that's why I have wrapping
// function. It just lets me call clickHandler in the right context.
// clickHandler method also needs to know what link is being clicked
// so we pass that in as parameter.
self.container.on(self.eventName,
self.options.linkSelector,
function() {
self.clickHandler($(this));
})
}
MyPlugin.prototype.clickHandler = function(clickedLink) {
var dataLinkId = clickedLink.data('link');
this.container.find('[data-window="' + dataLinkId + '"]').toggle();
}
$.fn.myPlugin = function(options) {
return this.each(function () {
var pluginInstance = new MyPlugin($(this), options);
pluginInstance.attachClickHandlers();
});
};
})(jQuery, window, document);
在此实现中,MyPlugin是一个类(在javascript意义上的单词类),它使您能够以其行为方式处理每个特定点。并介绍各种OOP功能。