`
LeeYee
  • 浏览: 69411 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【译】jQuery插件编写

阅读更多

最新内容请查看:http://leeyee.github.io/blog/2012/12/02/jquery-plugins-authoring 

 

jQuery插件编写(Plugins/Authoring)

原文地址http://docs.jquery.com/Plugins/Authoring

So you've become comfortable with jQuery and would like to learn how to write your own plugins. Great! You're in the right spot. Extending jQuery with plugins and methods is very powerful and can save you and your peers a lot of development time by abstracting your most clever functions into plugins. This post will outline the basics, best practices, and common pitfalls to watch out for as you begin writing your plugin.

当你已经熟练掌握jQuery并且想学习如何编写属于自己的插件程序时,你可以参看这篇文章。使用插件程序和方法扩展jQuery是非常强大的。你可以将一些想法抽象为函数并封装到插件中以便为你和你的同事节省许多开发时间。

目录(CONTENTS)

  1. 入门知识(Getting Started)

  2. 上下文(Context)

  3. 基本要素(The Basics)

  4. 保持可链通性(Maintaining Chainability)

  5. 默认值和可选项(Defaults and Options)

  6. 命名空间(Namespacing)

    6.1 插件方法(Plugin Methods)

    6.2 事件(Events)

    6.3 数据(Data)

  7. 总结和最佳实践(Summary and Best Practices)

  8. 翻译(Translations)

入门知识(Getting Started)

To write a jQuery plugin, start by adding a new function property to the jQuery.fn object where the name of the property is the name of your plugin:

编写jQuery插件,是从添加一个新的函数属性到jQuery.fn对象开始的,其中新的函数属性名为你要编写插件的名称:

jQuery.fn.myPlugin = function() {
    // Do your awesome plugin stuff here
};

But wait! Where's my awesome dollar sign that I know and love? It's still there, however to make sure that your plugin doesn't collide with other libraries that might use the dollar sign, it's a best practice to pass jQuery to an IIFE (Immediately Invoked Function Expression) that maps it to the dollar sign so it can't be overwritten by another library in the scope of its execution.

但是请等一下,我们喜爱的万能$符号在哪里?它仍然在哪里,然而为了确保你的插件不会与其他可能使用$符号的javascript库冲突,一个最佳的实践是将jQuery对象当做参数传递到一个可立即执行的函数表达式中(IIFE),该函数表达式会通过$符号来映射jQuery对象,这样在该函数表达式内,$符号将不会被在其可执行的作用域中的其他库所覆盖。

(function( $ ) {
    $.fn.myPlugin = function() {
        // Do your awesome plugin stuff here
    };
})( jQuery );

Ah, that's better. Now within that closure, we can use the dollar sign in place of jQuery as much as we like.

这样就可以了。现在通过闭包,我们就能使用我们喜爱的$符号代替jQuery对象了。

上下文(Context)

Now that we have our shell we can start writing our actual plugin code. But before we do that, I'd like to say a word about context. In the immediate scope of the plugin function, the this keyword refers to the jQuery object the plugin was invoked on. This is a common slip up due to the fact that in other instances where jQuery accepts a callback, the this keyword refers to the native DOM element. This often leads to developers unnecessarily wrapping the this keyword (again) in the jQuery function.

现在,有了插件外壳,我们就可以开始编写真正的插件代码了。但是在此之前,我想要谈谈上下文。在插件函数的当前域中,this 关键字是指代被调用插件中的jQuery对象的。这是一个常见的疏忽,因为在jQuery接受回调的其他情况中,this 关键字指代的是原生DOM元素。这常常会导致开发人员不必要地使用jQuery函数来包装 this 关键字。

(function( $ ){
    $.fn.myPlugin = function() {
        // there's no need to do $(this) because
        // "this" is already a jquery object
        // $(this) would be the same as $($('#element'));
        // 这里不需要执行$(this),
        // 因为this已经是一个jQuery object对象了
        // $(this) 等价于 $($('#element'));
        this.fadeIn('normal', function(){
            // the this keyword is a DOM element
        });
    };
})( jQuery );
$('#element').myPlugin();
基本要素(The Basics)

Now that we understand the context of jQuery plugins, let's write a plugin that actually does something.

现在,在了解了jQuery插件的上下文后,我们来编写一个实现了一些功能的插件。

(function( $ ){
    $.fn.maxHeight = function() {
        var max = 0;
        this.each(function() {
            max = Math.max( max, $(this).height() );
        });
        return max;
    };
})( jQuery );
// Returns the height of the tallest div
var tallest = $('div').maxHeight(); 

This is a simple plugin that leverages .height() to return the height of the tallest div in the page.

这是一个简单的插件,通过调用 .height() 来获取页面最高div元素的高度。

保持可链通性(Maintaining Chainability)

The previous example returns an integer value of the tallest div on the page, but often times the intent of a plugin is simply modify the collection of elements in some way, and pass them along to the next method in the chain. This is the beauty of jQuery's design and is one of the reasons jQuery is so popular. So to maintain chainability in a plugin, you must make sure your plugin returns the this keyword.

前面的示例返回一个整数值。但是大多数时候编写插件的意图是在某种程度上简单的修改一系列的元素,并且传递他们到另一个方法。这是jQuery优雅的设计之处和如此受欢迎的原因之一。因此为了维护插件中代码的可链通性,必须保证插件返回 this 关键字。

(function( $ ){
    $.fn.lockDimensions = function( type ) {  
        return this.each(function() {
            var $this = $(this);
            if ( !type || type == 'width' ) {
                $this.width( $this.width() );
            }
            if ( !type || type == 'height' ) {
                $this.height( $this.height() );
            }
        });
    };
})( jQuery );

$('div').lockDimensions('width').css('color', 'red');

Because the plugin returns the this keyword in its immediate scope, it maintains chainability and the jQuery collection can continue to be manipulated by jQuery methods, such as .css. So if your plugin doesn't return an intrinsic value, you should always return the this keyword in the immediate scope of the plugin function. Also, as you might assume, arguments you pass in your plugin invocation get passed to the immediate scope of the plugin function. So in the previous example, the string 'width' becomes the type argument for the plugin function.

因为插件在其当前的作用范围内返回了 this 关键字,所以就维持了可链通性,返回的jQuery对象集合也就可以继续被jQuery方法操作,比如 .css。假如插件不能返回一个内在值,那么就应该总是返回在其当前作用范围内的this 关键字。另外,如你所想,插件调用中的参数也传递到了当前作用范围内的插件函数中。所以在上述示例中,字符串'width'就变成了插件函数中的一个 type 参数。

默认值和可选项(Defaults and Options)

For more complex and customizable plugins that provide many options, it's a best practice to have default settings that can get extended (using $.extend) when the plugin is invoked. So instead of calling a plugin with a large number of arguments, you can call it with one argument which is an object literal of the settings you would like to override. Here's how you do it.

对于许多包含可选项的复杂可定制化插件,最好的方式是有一些能在被调用时可扩展(使用$.extend)的默认设置。这样就可以避免在调用插件时传递大量参数,取而代之的是在调用时使用一个需要覆盖掉的参数对象。下面就是如何实现他。

(function( $ ){
    $.fn.tooltip = function( options ) {  
        // Create some defaults, extending them with any options that were provided
        var settings = $.extend( {
            'location'         : 'top',
            'background-color' : 'blue'
        }, options);

        return this.each(function() {        
            // Tooltip plugin code here
        });
    };
})( jQuery );

$('div').tooltip({
    'location' : 'left'
});

In this example, after calling the tooltip plugin with the given options, the default location setting gets overridden to become 'left', while the background-color setting remains the default 'blue'. So the final settings object ends up looking like this:

在这例子中,当使用给定的可选项调用 tooltip 插件方法后,默认的 'location' 属性会被设置成 'left', 而 'background-color' 属性则保持不变。所以最终的 'settings' 对象看来是这样的:

{
    'location'         : 'left',
    'background-color' : 'blue'
}

This is a great way to offer a highly configurable plugin without requiring the developer to define all available options.

这是一种很好的方式。它提供了一个高度可配置的插件,而不需要开发人员去定义所有的可用选项。

命名空间(Namespacing)

Properly namespacing your plugin is a very important part of plugin development. Namespacing correctly assures that your plugin will have a very low chance of being overwritten by other plugins or code living on the same page. Namespacing also makes your life easier as a plugin developer because it helps you keep better track of your methods, events and data.

为你的插件设置一个适当的命名空间是插件开发中非常重要的一部分。合理的命名空间可以降低你的插件被另一些插件或者当前页面上的代码覆盖的几率。命名空间也可以让你的开发变得容易,它可以让你更好的跟踪方法、事件和数据。

插件方法(Plugin Methods)

Under no circumstance should a single plugin ever claim more than one namespace in the jQuery.fn object.

在任何情况下,一个单独的插件在jQuery.fn对象上的命名空间都不应超过一个。

(function( $ ){
    $.fn.tooltip = function( options ) { 
        // THIS
    };
    $.fn.tooltipShow = function( ) {
        // IS
    };
    $.fn.tooltipHide = function( ) { 
        // BAD
    };
    $.fn.tooltipUpdate = function( content ) { 
        // !!!  
    };
})( jQuery );

This is a discouraged because it clutters up the $.fn namespace. To remedy this, you should collect all of your plugin's methods in an object literal and call them by passing the string name of the method to the plugin.

这样做是不被提倡的,因为它会使$.fn命名空间变得混乱。为了解决这个问题,你应该将所有插件的方法存放在一个对象字面量中,然后通过传递方法的字符串名称来调用。

(function( $ ){
    var methods = {
        init : function( options ) { 
            // THIS 
        },
        show : function( ) {
            // IS
        },
        hide : function( ) { 
            // GOOD
        },
        update : function( content ) { 
            // !!! 
        }
    };

    $.fn.tooltip = function( method ) {
    // Method calling logic
        if ( methods[method] ) {
            return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
        }    
    };
})( jQuery );

// calls the init method
$('div').tooltip(); 

// calls the init method
$('div').tooltip({
    foo : 'bar'
});
// calls the hide method
$('div').tooltip('hide'); 
// calls the update method
$('div').tooltip('update', 'This is the new tooltip content!'); 

This type of plugin architecture allows you to encapsulate all of your methods in the plugin's parent closure, and call them by first passing the string name of the method, and then passing any additional parameters you might need for that method. This type of method encapsulation and architecture is a standard in the jQuery plugin community and it used by countless plugins, including the plugins and widgets in jQueryUI.

这种类型的插件结构允许在插件的父闭包中封装所有的方法,然后通过先传递方法的字符串名称,再传递其他一些这个方法可能用到的参数来调用。这种方式的方法封装和架构在jQuery插件社区是一种标准并被无数的插件采用,包括jQueryUI插件和组件。

事件(Events)

A lesser known feature of the bind method is that is allows for namespacing of bound events. If your plugin binds an event, its a good practice to namespace it. This way, if you need to unbind it later, you can do so without interfering with other events that might have been bound to the same type of event. You can namespace your events by appending “.< namespace >”the type of event you're binding.

对于bind方法一个鲜有人知的特性是允许为绑定的事件声明命名空间。假如你的插件绑定了一个事件,一个好的处理方式是为该事件添加命名空间。通过这种方式,假如随后你需要解除绑定(unbind),就可以在不影响其他可能已经绑定了相同类型事件的情况下解除绑定。你可以通过添加.<namespace>给你要绑定的事件添加命名空间。

(function( $ ){
    var methods = {
        init : function( options ) {
            return this.each(function(){
                $(window).bind('resize.tooltip', methods.reposition);
            });
        },
        destroy : function( ) {
            return this.each(function(){
                $(window).unbind('.tooltip');
            })
        },
        reposition : function( ) { 
            // ... 
        },
        show : function( ) { 
            // ... 
        },
        hide : function( ) {
            // ... 
        },
        update : function( content ) { 
            // ...
        }
    };

    $.fn.tooltip = function( method ) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
        }    
    };
})( jQuery );

$('#fun').tooltip();
// Some time later...
$('#fun').tooltip('destroy');

In this example, when the tooltip is initialized with the init method, it binds the reposition method to the resize event of the window under the namespace 'tooltip'. Later, if the developer needs to destroy the tooltip, we can unbind the events bound by the plugin by passing its namespace, in this case 'tooltip', to the unbind method. This allows us to safely unbind plugin events without accidentally unbinding events that may have been bound outside of the plugin.

在这个示例中,当 tooltip 使用 init 方法初始化时,他会绑定 reposition 方法到window对象的 resize 事件上,这些都是在 'tooltip' 命名空间下进行的。之后,如果开发人员需要销毁 tooltip ,就可以通过传递命名空间来解除该命名空间下绑定的事件。这让我们可以安全的解除通过插件绑定的事件,而不用担心将通过插件外其他方式绑定的事件也解除掉。

数据(Data)

Often times in plugin development, you may need to maintain state or check if your plugin has already been initialized on a given element. Using jQuery's data method is a great way to keep track of variables on a per element basis. However, rather than keeping track of a bunch of separate data calls with different names, it's best to use a single object literal to house all of your variables, and access that object by a single data namespace.

通常在插件开发中,可能需要维护状态或者检测插件在给定的元素上是否已被初始化。使用jquery 的 data 方法可以很好的跟踪基于每一个元素的变量。然而,相比跟踪大量有着不同名字的单独数据,还不如使用一个单独对象的字面量去存储所有变量并通过单一数据命名空间来访问此对象。

(function( $ ){
    var methods = {
        init : function( options ) {
            return this.each(function(){
                var $this = $(this),
                data = $this.data('tooltip'),
                tooltip = $('<div />', {
                    text : $this.attr('title')
                });
            // If the plugin hasn't been initialized yet
                if ( ! data ) {
                    /*
                    Do more setup stuff here
                    */
                    $(this).data('tooltip', {
                        target : $this,
                        tooltip : tooltip
                    });
                }
            });
        },
        destroy : function( ) {
            return this.each(function(){
                var $this = $(this),
                data = $this.data('tooltip');
                // Namespacing FTW
                $(window).unbind('.tooltip');
                data.tooltip.remove();
                $this.removeData('tooltip');
            })
        },
        reposition : function( ) { // ... },
        show : function( ) { // ... },
        hide : function( ) { // ... },
        update : function( content ) { // ...}
    };

    $.fn.tooltip = function( method ) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
        }    
    };
})( jQuery );

Using data helps you keep track of variables and state across method calls from your plugin. Namespacing your data into one object literal makes it easy to access all of your plugin's properties from one central location, as well as reducing the data namespace which allows for easy removal if need be.

使用数据有助于跟踪变量及来自插件方法调用间的状态。命名空间数据到一个对象字面量中,从一个中心位置来访问 以便从一个中心位置容易的访问所有的插件属性,同时如果有需要还可以轻松的移除不需要的命名空间。

总结和最佳实践(Summary and Best Practices)

Writing jQuery plugins allows you to make the most out of the library and abstract your most clever and useful functions out into reusable code that can save you time and make your development even more efficient. Here's a brief summary of the post and what to keep in mind when developing your next jQuery plugin:

编写jQuery插件允许你实现最有利用效率的库,允许你抽象有用的函数到可重用代码中,从而为你节省大量开发时间,使你的开发团队更加高效。下面是一些一些在开发jQuery插件过程中应时刻牢记的简要的总结:

  1. Always wrap your plugin in a closure: (function( $ ){ /* plugin goes here */ })( jQuery );

    始终将你的插件封装在一个闭包中:(function($) { /* plugin goes here */ })( jQuery );

  2. Don't redundantly wrap the this keyword in the immediate scope of your plugin's function

    不要在插件函数的当前作用域中使用$(this)多余的处理 this 关键字。

  3. Unless you're returning an intrinsic value from your plugin, always have your plugin's function return the this keyword to maintain chainability.

    除非返回一个内部值,否则总是让你的插件函数返回 this 关键字以保持链通性。

  4. Rather than requiring a lengthy amount of arguments, pass your plugin settings in an object literal that can be extended over the plugin's defaults.

    不要为你的插件函数定义过多的参数,而是通过传递一个可被扩展到插件默认值的对象字面量来传递参数。

  5. Don't clutter the jQuery.fn object with more than one namespace per plugin.

    保证每个插件中只有一个 jQuery.fn 对象的命名空间

  6. Always namespace your methods, events and data.

    总是为自己的方法、事件和数据设置命名空间。

Translations

If you have translated this article or have some similar one on your blog post a link here. Please mark Full Translated articles with (t) and similar ones with (s).

TOP

0
0
分享到:
评论

相关推荐

    jquery插件编写指南

    这里提供最基础的jquery插件编辑方法,为jquery插件学习者提供帮助。

    Jquery扩展 编写自已的Jquery插件

    这是一本带领你一步步编写自己的Jquery自定义插件或控件的好书,本书共14章,内容充实,是不本相当不错的前端开发学习资料

    jquery插件使用方法大全

    plugin历史版本1、新的事件.on() .off()3、动画的改进1.42版介绍JQuery插件让Dreamweaver支持提示代码功能引入JQuery展开编辑本段简介  jQuery由美国人John Resig创建,至今已吸引了来自世界各地的众多javascript...

    eclipse插件 - jQuery

    我们在编写js的时候,如果采用了jquery框架,当然很希望Eclipse能帮我们完成代码自动完成的功能了,但Eclipse默认只是支持js的代码自动完成,利用这个插件,可以让Eclipse支持jquery的代码自动完成功能(前提:...

    eclipse上支持jquery插件

    eclipse上支持jquery的插件,使eclipse能够提供jquery提示,更快编写jquery代码

    jQuery插件开发学习

    NULL 博文链接:https://zhoucl.iteye.com/blog/1239737

    JQuery编写百叶窗Flash插件

    使用Jquery编写的一个Flash图片轮播插件,类似于百叶窗效果。 随机的特效有: 1、左上角缩小至0 2、分行slideUp 3、渐变 4、整体上移 5、整体下移 6、整体左移 7、整体右移 8、行阶梯性左移 9、行阶梯性右移 10、行...

    Jquery插件编写简明教程

    主要介绍了Jquery插件编写简明教程,jquery插件开发实例,需要的朋友可以参考下

    jquery时间插件

    jquery时间插件laydate,有范例,有使用说明,很实用,兼容性好。

    jQuery插件编写步骤详解

    主要介绍了jQuery插件编写步骤,详细分析了jQuery实现插件功能的具体步骤与相关操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下

    JQuery编写百叶窗Flash插件 20121011

    使用Jquery编写的一个Flash图片轮播插件,类似于百叶窗效果。 随机的特效有: 1、左上角缩小至0 2、分行slideUp 3、渐变 4、整体上移 5、整体下移 6、整体左移 7、整体右移 8、行阶梯性左移 9、行阶梯性...

    基于jquery插件编写countdown计时器

    主要为大家详细介绍了jquery插件编写countdown计时器,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    Jquery快速学(五,常用的插件应用与编写)

    原创jquery快速学(五)常用的插件应用与编写。 本教程提供免费的源码与教学文档,欢迎广大朋友下载。

    可定制的实时搜索JQUERY插件.zip

    可定制的实时搜索JQUERY插件是一款很简单的可定制的jquery搜索插件,与IE7 ,Chrome浏览器,火狐,Safari和jQuery1.8.1,1.9.1,1.11.0,2.1.0兼容。

    dreamweaver的几个实用插件 zen coding,html5扩展,jquery插件

    Zen.Coding-Dreamweaver.v0.6 zen.coding ...jQuery_api_for_dw4 dreamweaver cs4的jquery插件 DW5插件-jQuery_api_for_dwcs5 dreamweaver cs5的jquery插件 AdobeDreamweaver-11.0-All-Update dreamweaver的html5扩展

    jquery插件编写

    关于JQUERY插件的编写帮助

    写或读JS代码的时候总有些地方感觉模模糊糊的,于是花了点时间在网上找并稍微整理了一下

    jQuery树状json数据转表格插件.zip

    jQuery树状json数据转表格插件是一款使用原生ul以及jquery编写的插件。

Global site tag (gtag.js) - Google Analytics