现在我们已经了解了插件开发的基础知识,我们可以更深入地挖掘。因为最终插件是一个函数,它为我们提供了组织所需的范围。还记得我们在学习模板时整理我们的代码吗?我们可以在插件中使用一些相同的概念。
但首先,我认为 jQuery 插件架构可以从一些样板代码中获益。也许您熟悉HTML5 Boilerplate,它提供了一堆智能默认值。jQuery 插件样板是相同类型的东西。节省了一些打字工作,并让您走上一条智能开发的道路。
我偶然发现了一个名为jQuery Boilerplate的项目,我猜想它应该不错。但我还没有深入研究那个。相反,我非常喜欢 Doug Neiner 的Starter。您提供一个名称、一些默认值和一些选择,它将为您生成该样板结构。
我们决定创建一个名为 lodgeSlider 的滑块,并带有一个简单的速度参数,最终得到以下代码
(function($){
$.lodgeSlider = function(el, options){
// To avoid scope issues, use 'base' instead of 'this'
// to reference this class from internal events and functions.
var base = this;
// Access to jQuery and DOM versions of element
base.$el = $(el);
base.el = el;
// Add a reverse reference to the DOM object
base.$el.data("lodgeSlider", base);
base.init = function(){
base.options = $.extend({},$.lodgeSlider.defaultOptions, options);
// Put your initialization code here
};
// Sample Function, Uncomment to use
// base.functionName = function(paramaters){
//
// };
// Run initializer
base.init();
};
$.lodgeSlider.defaultOptions = {
speed: 300
};
$.fn.lodgeSlider = function(options){
return this.each(function(){
(new $.lodgeSlider(this, options));
});
};
})(jQuery);
其中很多看起来应该很熟悉。有一个 IIFE 包装插件以确保安全。在 jQuery 对象上创建了一个函数。立即调用了一个名为 init 的函数。在 jQuery 对象上创建了一个方法,该方法返回一个 jQuery 对象。创建了一些变量来缓存我们可能再次使用的引用。大多是我们之前见过的内容。
也许有两件新东西。一个是其中的 options 对象。您可以看到硬编码的 300 值。但也可以看到带有 $.extend()
的行。这是一个 jQuery 函数,用于将两个对象合并为一个,其中一个对象优先于另一个对象。当我们调用插件时,也许像这样
$("#slider-1").lodgeslider();
我们没有传入任何选项,并且该空对象与我们的硬编码对象合并,并且默认值在插件内部可用。但我们也可以这样调用它
$("#slider-1").lodgeslider({
speed: 500
});
我们在这里将一个对象作为参数传递。该对象与我们的硬编码对象合并,优先于后者,并且我们传递的值成为插件中可用的值。很酷。
另一件新事物是使用 .data()
的那个奇怪的部分。我们创建了 base 变量来引用函数本身,该函数为插件调用的每个元素重新创建。例如,假设我们在 $(".slider")
上调用了插件 - 页面上可能有两个具有类名 slider
的元素。each 循环运行,并且创建了 lodgeSlider 函数的两个实例。在每一个实例中,我们都将对它的引用附加到元素本身。这样,我们可以从我们拥有的该元素的任何引用中调用内部插件方法。
比如也许
$(".the-first-slider").data("lodgeSlider").changeSlide(2);
只是给我们提供了一种在需要时使用插件方法的好方法。
在这次插件构建冒险中,我们并没有取得巨大的进步
查看 CodePen 上 Chris Coyier (@chriscoyier) 的作品 从头开始构建滑块
老实说,世界可能不需要另一个滑块插件。但是,您可以看到它们可能会变得多么复杂。以下是一些想法
- 可以有回调函数(或自定义事件)用于滑块更改之前和之后、滑块设置之后、滑块拆除之后等。
- 宽度可以基于百分比,并在浏览器窗口发生变化时重新计算。
- 导航可以动态构建,而不是在标记中强制要求。
- ID 和 #hash href 也可以动态创建。
- 可以添加诸如滑动之类的触摸事件,使滑块更友好(小圆点不友好)。
您执行的这些操作越多,插件的大小就越大。这就是为什么在功能、实用性、性能和大小之间取得平衡如此棘手,并且存在许多最终执行相同操作的不同插件的原因。
抱歉。我不明白为什么我们将未使用的方法设置为 jQuery
$.lodgeSlider = function(el, options){….
而不是声明私有变量
var lodgeSlider = function(el, options){….
这没什么大不了的,这只是一个习惯做法。插件需要 jQuery,因此将其附加到 jQuery 命名空间是一种强调这一点的方法。
有没有办法从 $.lodgeSlider 函数外部访问 init 函数,例如从 $.fn.lodgeSlider.public_method?