「jQuery插件开辟日志」(二)高等插件理念 - [翻译]

_Advanced Plugin Concepts_,翻译自 jQuery 官方网站。

默许设置的共有接口

关于上一篇文章末了的代码,我们可以革新,也应当革新的处所就是,为我们的插件的默许设置供应共有接口,使得用户可以直接变动默许设置。

如许做的优点就是可以让用户用起码的代码量来定制我们的插件。此次的例子是:

// Plugin definition.
$.fn.hilight = function( options ) {
 
    // Extend our default options with those provided.
    // Note that the first argument to extend is an empty
    // object – this is to keep from overriding our "defaults" object.
    var opts = $.extend( {}, $.fn.hilight.defaults, options );
 
    // Our plugin implementation code goes here.
 
};
 
// Plugin defaults – added as a property on our plugin function.
$.fn.hilight.defaults = {
    foreground: "red",
    background: "yellow"
};

如今用户可以如许变动默许设定:

// This needs only be called once and does not
// have to be called from within a "ready" block
$.fn.hilight.defaults.foreground = "blue";

如许运用我们的插件:

$( "#myDiv" ).hilight();

你可以看到,我们许可用户运用仅仅一行代码就掩盖了某个默许设定。除此之外,用户依然可以传入参数来掩盖他们设定的默许设置。

// Override plugin default foreground color.
$.fn.hilight.defaults.foreground = "blue";
 
// ...
 
// Invoke plugin using new defaults.
$( ".hilightDiv" ).hilight();
 
// ...
 
// Override default by passing options to plugin method.
$( "#green" ).hilight({
    foreground: "green"
});

隶属函数的大众接口

为某些隶属函数提大众接口,可以异常好的去扩大和让他人扩大你的插件。

举个例子,我们的插件能够完成了一个叫 format 的函数, 这个函数格式化强调文本的情势。我们在 hilight 函数下面定义了 format 的默许要领。

// Plugin definition.
$.fn.hilight = function( options ) {
 
    // Iterate and reformat each matched element.
    return this.each(function() {
 
        var elem = $( this );
 
        // ...
 
        var markup = elem.html();
 
        // Call our format function.
        markup = $.fn.hilight.format( markup );
 
        elem.html( markup );
 
    });
 
};
 
// Define our format function.
$.fn.hilight.format = function( txt ) {
    return "<strong>" + txt + "</strong>";
};

我们也可以在设置中心许可一个回调函数,来掩盖默许的 format 函数, 这也是一个支撑定制的异常棒的要领。
运用这些手艺,其他人可以异常轻易的定制你的插件,然后宣布。换句话说,其他人可认为你的插件来写插件。

考虑到这篇文章里这个惨白的例子并非异常具有说服力,一个实际的例子就是 Cycle Plugin。这个插件是一个幻灯片插件,内置异常多切换殊效,像转动、滑动、淡出等。然则实际上它不能够定义每一个人想要的结果,那末插件的扩大性就异常重要了。

Cycle Plugin 对外暴露了一个 transitions 对象。 在这里用户可以本身定义他们的切换殊效。

$.fn.cycle.transitions = {
 
    // ...
 
};

坚持私有函数私有

对外供应一部份你的插件的大众接口确切很壮大,然则你要想清晰哪些部份须要供应给大众接口,哪些不须要。当函数一旦暴露在外,任何对参数和语义(函数的功用)的变动都邑摧毁向后兼容性。一般来说,假如你不确定一个要领是不是应当设为公有,那末或许答案是不。

所以我们如安在不搅散定名空间而且坚持私有的状况下定义更多的函数呢?这就是闭包的事变了。

为了展现怎样处置惩罚这个题目,我们在我们的插件里加了一个函数 debug。这个函数在 console 中输出选定的对象。我们将全部插件用一个函数包裹起来(上一篇文章也有提到)。

// Create closure.
(function( $ ) {
 
    // Plugin definition.
    $.fn.hilight = function( options ) {
        debug( this );
        // ...
    };
 
    // Private function for debugging.
    function debug( obj ) {
        if ( window.console && window.console.log ) {
            window.console.log( "hilight selection count: " + obj.length );
        }
    };
 
    // ...
 
// End of closure.
 
})( jQuery );

Bob & Sue(实例)

Bob 已建立了一个新的画廊插件(叫 “superGallery”)。这个插件使得一系列图片变得可导航的。Bob 一样还添加了一些动画结果使得插件变得越发风趣。他想让他的插件取得最大程度的可定制性,所以他写出了下面的代码:

jQuery.fn.superGallery = function( options ) {
 
    // Bob's default settings:
    var defaults = {
        textColor: "#000",
        backgroundColor: "#fff",
        fontSize: "1em",
        delay: "quite long",
        getTextFromTitle: true,
        getTextFromRel: false,
        getTextFromAlt: false,
        animateWidth: true,
        animateOpacity: true,
        animateHeight: true,
        animationDuration: 500,
        clickImgToGoToNext: true,
        clickImgToGoToLast: false,
        nextButtonText: "next",
        previousButtonText: "previous",
        nextButtonTextColor: "red",
        previousButtonTextColor: "red"
    };
 
    var settings = $.extend( {}, defaults, options );
 
    return this.each(function() {
        // Plugin code would go here...
    });
 
};

你想到的第一件事变能够就是,这个插件该有多大才完成这么多可定制功用。这个插件的体积能够完整没必要这么大。

Bob 对他的插件异常惬意。他以为他的插件会在差别的情形之下会是一个通用的处置惩罚方案。

Sue 决议去用一用这个新插件。她设置了一切的选项,然则她意想到,假如图片的宽度以低速变化的话,会取得越发好的结果。她赶忙去搜刮了 Bob 的文档,然则并没有找到 animateWidthDuration 相似的选项。

你看到题目了吗?

题目的关键是并非你的插件有若干个选项,而是有什么选项。

Bob 做的有点儿过了。他供应的定制性看起来很高,实在异常低。特别是考虑到一个人能够想要在这个插件中掌握的一切特征。Bob 犯了个毛病,它供应了异常多荒唐的选项,却不知让他的插件变得更难定制了。

一个更好的模子

所以如今异常显著了,Bob 须要一个新的定制模子。一个并没有摒弃必需的掌握和笼统细节的定制模子。

这里有一些发起,可以让你更好的建立一个可定制化插件。

不要建立本身的语法

运用你的插件的开发者不该当要去学一门新的言语或新的手艺,只需搞定他们的事情。

Bob 他为 delay 这个选项供应了最大的定制性。他设置了4个差别的耽误:

var delayDuration = 0;
 
switch ( settings.delay ) {
 
    case "very short":
        delayDuration = 100;
        break;
 
    case "quite short":
        delayDuration = 200;
        break;
 
    case "quite long":
        delayDuration = 300;
        break;
 
    case "very long":
        delayDuration = 400;
        break;
 
    default:
        delayDuration = 200;
 
}

这致使不单单议用户所能掌握的耽误程度变少了,还花费了比较多的空间。20行代码仅仅就为了定义一个耽误时刻,有点儿多了。

一个越发好的体式格局就是让用户本身传入耽误的时刻。

元素的完整掌握权

假如你的插件在DOM中建立了一些元素。那末你最好让用户有要领去掌握它。有些时刻这意味着供应给用户传入ID或许类名的要领。然则注重你的插件不该当全局依靠这些。

一个不好的完成:

// Plugin code
$( "<div class='gallery-wrapper' />" ).appendTo( "body" );

一个好一点儿的完成:

// Retain an internal reference:
var wrapper = $( "<div />" )
    .attr( settings.wrapperAttrs )
    .appendTo( settings.container );
 
// Easy to reference later...
wrapper.append( "..." );

注重我们运用了 .attr() 来增添特定的属性。所以我们的设置应当像如许:

var defaults = {
    wrapperAttrs : {
        class: "gallery-wrapper"
    },
    // ... rest of settings ...
};
 
// We can use the extend method to merge options/settings as usual:
// But with the added first parameter of TRUE to signify a DEEP COPY:
var settings = $.extend( true, {}, defaults, options );

关于CSS 也可以运用一样的要领来完成:

var defaults = {
    wrapperCSS: {},
    // ... rest of settings ...
};
 
// Later on in the plugin where we define the wrapper:
var wrapper = $( "<div />" )
    .attr( settings.wrapperAttrs )
    .css( settings.wrapperCSS ) // ** Set CSS!
    .appendTo( settings.container );

供应回调函数

假如你的插件是事宜驱动的话,最好为每一个事宜供应回调函数。

var defaults = {
 
    // We define an empty anonymous function so that
    // we don't need to check its existence before calling it.
    onImageShow : function() {},
 
    // ... rest of settings ...
 
};
 
// Later on in the plugin:
 
nextButton.on( "click", showNextImage );
 
function showNextImage() {
 
    // Returns reference to the next image node
    var image = getNextImage();
 
    // Stuff to show the image here...
 
    // Here's the callback:
    settings.onImageShow.call( image );
}

记着,这是一个衡量题目

你的插件不能够在一切的状况下都能事情。一样的,当你供应很少的掌握的要领的时刻,它也有能够没啥用。所以,衡量是异常重要的事变。以下有三点:

  • 灵活性:你的插件要处置惩罚若干种状况?

  • 大小:你的插件大小和它的功用相匹配吗?

  • 机能:你的插件不管什么状况都邑处置惩罚设置选项吗?影响速率吗?值得吗?

    原文作者:JasonKidd
    原文地址: https://segmentfault.com/a/1190000003559775
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞