怎么创建一个基本的jQuery插件 - How to Create a Basic Plugin

盖博简
2023-12-01

有时候你想要一些在你的整个代码可用的功能.例如, 或许你想有一个支持链式操作的单一方法 , 鉴于此, 你可以写一个插件来解决.

jQuery是如何工作的: jQuery Object Methods

在写我们的插件之前,我们首先要理解一点关于jQuery是如何工作的东西, 看下面的代码:

$( "a" ).css( "color", "red" );

这是相当简单的jQuery代码, 但是你知道幕后发生了什么吗? 无论何时你使用 $ 选择一个元素, 它会返回一个jQuery 对象. 这个对象包含了所有你使用过的方法, 还有所有符合选择器的元素. jQuery 对象从$.fn object 获得这些方法. 这个对象包含了所有的 jQuery object 方法, 如果我们想要写自己的方法 ,也需要包含这些.

基本的插件编写

来看看创建一个使文字变成绿色的插件. 我们需要做的只是增加一个叫做 greenify 的方法到 $.fn , 然后它将像其他任何的jQuery对象方法一样可用.

$.fn.greenify = function() {
    this.css( "color", "green" );
};
 
$( "a" ).greenify(); //使所有的链接变成绿色

注意使用 .css() 方法 , 其他方法 , 我们使用 this 而不是$(this), 这是因为我们的greenify函数像.css()方法一样是相同对象的一部分.


链式操作

这个步骤使得我们的插件真正的可用, jQuery 的其中一个特性就是链式操作. 就是你可以连续的使用五六个行为在同一个选择器中, 这是通过再次返回包含所有jQuery对象的原始jQuery对象完成的. 使我们的插件可以链式操作只要加上下面的一句代码:

$.fn.greenify = function() {
    this.css( "color", "green" );
    return this;
}
$( "a" ).greenify().addClass( "greenified" );

保护别名 $ 以及增加使用范围

$ 变量在JavaScript库中是非常受欢迎的, 如果你同时使用 jQuery和其他的库, you will have to make jQuery not use the $ with jQuery.noConflict(). However, this will break our plugin since it is written with the assumption that $ is an alias to the jQuery function. To work well with other plugins, and still use the jQuery $ alias, we need to put all of our code inside of an Immediately Invoked Function Expression, and then pass the function jQuery, and name the parameter $:

(function ( $ ) {
    $.fn.greenify = function() {
        this.css( "color", "green" );
        return this;
    };
}( jQuery ));

In addition, the primary purpose of an Immediately Invoked Function is to allow us to have our own private variables. Pretend we want a different color green, and we want to store it in a variable.

(function ( $ ) {
    var shade = "#556b2f";
    $.fn.greenify = function() {
        this.css( "color", shade );
        return this;
    };
 
}( jQuery ));

Minimizing Plugin Footprint

It's good practice when writing plugins to only take up one slot within $.fn. This reduces both the chance that your plugin will be overridden, and the chance that your plugin will override other plugins. In other words, this is bad:

(function( $ ) {
 
    $.fn.openPopup = function() {
        // Open popup code.
    };
 
    $.fn.closePopup = function() {
        // Close popup code.
    };
 
}( jQuery ));

It would be much better to have one slot, and use parameters to control what action that one slot performs.

(function( $ ) {
    $.fn.popup = function( action ) {
        if ( action === "open") {
            // Open popup code.
        }
        if ( action === "close" ) {
            // Close popup code.
        }
    };
}( jQuery ));

Using the each() Method

Your typical jQuery object will contain references to any number of DOM elements, and that's why jQuery objects are often referred to as collections. If you want to do any manipulating with specific elements (e.g. getting a data attribute, calculating specific positions) then you need to use .each() to loop through the elements.

$.fn.myNewPlugin = function() {
    return this.each(function() {
        // Do something to each element here.
    });
};

Notice that we return the results of .each() instead of returning this. Since .each() is already chainable, it returns this, which we then return. This is a better way to maintain chainability than what we've been doing so far.

Accepting Options

As your plugins get more and more complex, it's a good idea to make your plugin customizable by accepting options. The easiest way to do this, especially if there are lots of options, is with an object literal. Let's change our greenify plugin to accept some options.

(function ( $ ) {
    $.fn.greenify = function( options ) {
        // This is the easiest way to have default options.
        var settings = $.extend({
            // These are the defaults.
            color: "#556b2f",
            backgroundColor: "white"
        }, options );
        // Greenify the collection based on the settings variable.
        return this.css({
            color: settings.color,
            backgroundColor: settings.backgroundColor
        });
    };
}( jQuery ));

Example usage:

$( "div" ).greenify({
    color: "orange"
});

The default value for color of #556b2f gets overridden by $.extend() to be orange.

Putting It Together

Here's an example of a small plugin using some of the techniques we've discussed:

(function( $ ) {
 
    $.fn.showLinkLocation = function() {
 
        this.filter( "a" ).each(function() {
            var link = $( this );
            link.append( " (" + link.attr( "href" ) + ")" );
        });
 
        return this;
 
    };
 
}( jQuery ));
 
// Usage example:
$( "a" ).showLinkLocation();

This handy plugin goes through all anchors in the collection and appends the href attribute in parentheses.

<!-- Before plugin is called: -->
<a href="page.html">Foo</a>
 
<!-- After plugin is called: -->
<a href="page.html">Foo (page.html)</a>

Our plugin can be optimized though:

(function( $ ) {
    $.fn.showLinkLocation = function() {
        this.filter( "a" ).append(function() {
            return " (" + this.href + ")";
        });
        return this;
    };
}( jQuery ));

We're using the .append() method's capability to accept a callback, and the return value of that callback will determine what is appended to each element in the collection. Notice also that we're not using the .attr() method to retrieve the href attribute, because the native DOM API gives us easy access with the aptly named href property.


转载于:https://my.oschina.net/AARONWB/blog/501864

 类似资料: