In-depth understanding of JQuery plug-in development

Source: Internet
Author: User

In-depth understanding of JQuery plug-in development

If you see this article, I am sure you will undoubtedly think that jQuery is a simple library. JQuery may be easy to use, but it still has some strange points. People who are not familiar with its basic functions and concepts may be difficult to grasp. But don't worry. I have divided the code into a small part and provided a simple guide. The syntax may seem too complex, but it is very easy to understand if it comes into its thoughts and patterns.

Below, we have a basic layer of plug-ins:

// Shawn Khameneh // ExtraordinaryThoughts.com (function ($) {var privateFunction = function () {// code is run here} var methods = {init: function (options) {return this. each (function () {var $ this = $ (this); var settings = $ this. data ('ininname'); if (typeof (settings) = 'undefined') {var defaults = {propertyName: 'value', onSomeEvent: function () {}} settings = $. extend ({}, defaults, options); $ this. dat A ('ininname', settings);} else {settings = $. extend ({}, settings, options) ;}// code runs here}) ;}, destroy: function (options) {return $ (this ). each (function () {var $ this = $ (this); $ this. removeData ('ininname') ;}, val: function (options) {var someValue = this.eq(0).html (); return someValue ;}; $. fn. pluginName = function () {var method = arguments [0]; if (methods [method]) {method = methods [Method]; arguments = Array. prototype. slice. call (arguments, 1);} else if (typeof (method) = 'object' |! Method) {method = methods. init;} else {$. error ('method' + Method + 'does not exist on jQuery. pluginName '); return this;} return method. apply (this, arguments) ;}} (jQuery );

You may notice that the structure of the code I mentioned is very different from that of other plug-in codes. Depending on your usage and needs, the development methods of plug-ins may also be diversified. My goal is to clarify some concepts in the Code, so that you can find a suitable method to understand and develop a jQuery plug-in.

Now, let's dissect our code!

Container: an instant function execution

Basically, the code of each plug-in is contained in a function that is executed instantly, as follows:

(Function (arg1, arg2) {// code}) (arg1, arg2 );

An instant function, as its name implies, is a function. What makes it special is that it is contained in a pair of parentheses, which allows all code to run in the local scope of the anonymous function. This does not mean that the DOM (global variable) is blocked in the function, but that the external cannot access the public variables and object namespaces inside the function. This is a good start. When you declare your variables and objects, you don't have to worry about conflicting variable names and existing code.

Now, because all the public variables in the function cannot be accessed, it is a problem to use jQuery as an internal public variable. Just like a common function, real-time functions also pass in object parameters based on references. We can pass the jQuery object into the function as follows:

(Function ($) {// use $ to reference jQuery in a local scope}) (jQuery );

We passed in a function that passed in the public variable "jQuery" for immediate execution. In the local function (container), we can use“$”To reference it. That is to say, we call the container as a function, and the parameter of this function is jQuery. Because the referenced "jQuery" is passed in as a public variable, rather than its abbreviation "$", we can be compatible with the Prototype library. If you do not use Prototype or other“$”If you do not do this, it will not affect you, but it is still a good thing to know this usage.

Plug-in: A Function

A jQuery plug-in is essentially a huge function in the jQuery namespace. Of course, we can easily use "jQuery. pluginName = function "to achieve our goal, but if we do so, the code of our plug-in is in the unprotected exposure state. "JQuery. fn" is short for "jQuery. prototype", which means that when we get our plug-in through the jQuery namespace, it is only writable (unchangeable ). What can it actually do for you? It allows you to properly organize your code and understand how to protect your code from unnecessary modifications during running. This is a good practice!

Using a plug-in, we get a basic jQuery function:

(Function ($) {$. fn. pluginName = function (options) {// The code runs return this ;}} here) (jQuery );

The functions in the above Code can pass through
$('#element’).pluginName(). Note: How do I add the "return this" Statement; this small piece of code returns a set of original elements (included in this) and these elements are wrapped by a jQuery object. You should also note that "this" is a jQuery object in this specific scope, which is equivalent$(‘#element’).

Based on the returned object, we can conclude that in the above Code$(‘#element’).pluginName()Effect and usage$(‘#element’)The effect is the same. In your instant function execution scope, it is not necessary to use$(this)To wrap this into a jQuery object, because this itself is already a packaged jQuery object.

Multiple elements: Understanding Sizzle

The selector engine used by jQuery is called Sizzle. Sizzle can provide multi-element operations for your function (for example, for all elements with the same class name ). This is one of several excellent jQuery features, but it is also something you need to consider when developing plug-ins. Even if you are not prepared to provide multi-element support for your plug-in, it is still a good practice to prepare for it.

Here I have added a small piece of code that enables your plug-in code to work independently for each element in a multi-element collection:

Function ($) {// Add your plug-in code to the protected "fn" namespace in jQuery, and use "pluginName" as the plug-in function name $. fn. pluginName = function (options) {// return "this" (the return value of function each () is also this) for chained calls. Return this. each (function () {// run the code here. You can use "this" to obtain each individual element // For example: $ (this ). show (); var $ this = $ (this) ;}}) (jQuery );

In the above sample code, I do not use each () to run code on each element in my selector. In the local scope of the function called by each (), you can use this to reference each element that is processed separately, that is, you can use (This) to reference its jQuery object. In the local scope, I use This variable stores jQuery objects instead of using $ (this) every time you call a function. this is a good practice. Of course, this is not always necessary; but I have included it in my code. Note that we will use each () for each separate method, so that we can return the value we need instead of a jQuery object.

The following is an example. If our plug-in supports a val method, it can return the value we need:

$ ('# Element'). pluginName ('val '); // return the value we need instead of a jQuery object.
Function: public and private methods

A basic function may work well in some cases, but a slightly more complex plug-in requires various methods and private functions. You may use different namespaces to provide various methods for your plug-ins, but it is best not to confuse your source code with excessive namespaces.

The following code defines a JSON object that stores public methods and shows how to use the main function in the plug-in to determine which methods are called, and how to make the method work on each element of the selector.

(Function ($) {// in our plug-in container, create a public variable to construct a private method var privateFunction = function () {// code here} // create an object by literally, and store the common method var methods ={// define each separate method in the literal object init: function () {// for better flexibility, the independent function is implemented and the code return this is executed for each element of the selector in each method. each (function () {// create a jQuery object var $ this = $ (this) for each independent element; // execute code // For example: privateFunction () ;}) ;}, destroy: function () {// return this for each element of the selector. each (function (){// Execute Code}) ;}}; $. fn. pluginName = function () {// obtain our method. Unfortunately, if we use function (method) {} for implementation, this will destroy all var method = arguments [0]; // check whether the method exists if (methods [method]) {// if the method exists, save it for use // Note: I am doing this to make it easier to use each () method = methods [method]; // if the method does not exist, check whether the object is a JSON object or the method is not passed in.} else if (typeof (method) = 'object' |! Method) {// if we input an object parameter or there is no parameter at all, the init method will be called method = methods. init;} else {// if the method does not exist or the parameter is not passed in, an error is returned. The method to be called is not called correctly $. error ('method' + Method + 'does not exist on jQuery. pluginName '); return this;} // call the method we selected // once again, pay attention to how we transfer each () from here to the return method of each separate method. call (this) ;}} (jQuery );

Note that I regard privateFunction as a global variable in a function. Considering that all code runs in the plug-in container, this method is acceptable because it is only available in the scope of the plug-in. In the main function of the plug-in, I checked whether the method pointed to by the input parameter exists. If the method does not exist or the input parameter is an object, the init method will be run. Finally, if the input parameter is not an object but a non-existent method, an error message is returned.

Also note how I use it in every methodthis.each(). When we callmethod.call(this)This is actually a jQuery object, which is passed into every method as this. Therefore, in the instant scope of our method, it is already a jQuery object. Only wheneach()In the called function, We need to wrap this in a jQuery object.

The following are examples of usage:

/* Note that these examples can run correctly in the current plug-in code. Not all plug-ins use the same code structure * // name each class ". execute the init method $ ('. classname '). pluginName (); $ ('. classname '). pluginName ('init '); $ ('. classname '). pluginName ('init ', {}); // input the "{}" object to the init method as the function parameter $ ('. classname '). pluginName ({}); // input the "{}" object to the init method as the function parameter. // name each class ". execute the destroy method $ ('. classname '). pluginName ('deststroy'); $ ('. classname '). pluginName ('deststroy', {}); // pass the "{}" object to the destroy method as the function parameter. // all codes can run normally. $ ('. classname '). pluginName ('init ', 'argument1', 'argument2 '); // pass "argument 1" and "argument 2" into "init" // incorrect usage $ ('. classname '). pluginName ('nonexistantmethod'); $ ('. classname '). pluginName ('nonexistantmethod', {}); $ ('. classname '). pluginName ('argument 1'); // you will try to call the "argument 1" method $ ('. classname '). pluginName ('argument 1', 'argument 2'); // calls the "argument 1", "argument 2" method $ ('. classname '). pluginName ('privatefunction '); // 'privatefunction' is not a method

In the preceding example, {} appears multiple times, indicating parameters in the input method. In this section, the above Code can run normally, but the parameters are not passed into the method. Continue to the next section and you will know how to pass parameters to the method.

Set the plug-in: input parameters

Many plug-ins support parameter input, such as configuration parameters and callback functions. You can pass in JS key-Value Pair objects or function parameters to provide information for methods. If your method supports more than one or two parameters, there is no more appropriate way than passing in object parameters.

(Function ($) {var methods = {init: function (options) {// execute the return this method on each element. each (function () {var $ this = $ (this); // create a default setting object var defaults = {propertyName: 'value', onSomeEvent: function () {}} // use the extend method to create a settings object var settings = $ from the options and ults objects. extend ({}, defaults, options); // execute code}) ;}}; $. fn. pluginName = function () {var method = arguments [0]; if (methods [method]) {method = Methods [method]; // Our method is passed in as a parameter and deleted from the parameter list, because it is not required to call the method arguments = Array. prototype. slice. call (arguments, 1);} else if (typeof (method) = 'object' |! Method) {method = methods. init;} else {$. error ('method' + Method + 'does not exist on jQuery. pluginName '); return this;} // use the apply method to call our method and input the return method parameter. apply (this, arguments) ;}} (jQuery );

As shown above, an "options" parameter is added to the method, and "arguments" is also added to the main function. If a method has been declared, the parameters that call the method will be deleted from the parameter list before the parameter is passed in to the method. I used "apply ()" to replace "call ()". "apply ()" is essentially the same job as "call, but the difference is that it allows parameter input. This structure also allows the input of multiple parameters. If you want to do this, you can also modify the parameter list for your method, for example, "init: function (arg1, arg2) {}".

If you use a JS object as a parameter, you may need to define a default object. Once the default object is declared, you can use“$.extend”Combine the values of parameter objects and default objects to form a new parameter object (in our example, "settings ");

Here are some examples to demonstrate the above logic:

var options = {    customParameter: 'Test 1',    propertyName: 'Test 2'}var defaults = {    propertyName: 'Test 3',    onSomeEvent: 'Test 4'}var settings = $.extend({}, defaults, options);/*settings == {propertyName: 'Test 2',onSomeEvent: 'Test 4',customParameter: 'Test 1'}*/
Save settings: Add persistent data

Sometimes you want to save settings and information in your plug-in. In this case, the "data ()" function in jQuery can be used. It is very simple to use. It will try to get the data related to the element. If the data does not exist, it will create the corresponding data and add it to the element. Once you use "data ()" to add information for the element, make sure you have remembered that when you no longer need data, use "removeData ()" to delete the corresponding data.

// Shawn Khameneh // ExtraordinaryThoughts.com (function ($) {var privateFunction = function () {// Execution Code} var methods = {init: function (options) {// execute the return this method on each element. each (function () {var $ this = $ (this); // try to get settings. If it does not exist, return "undefined" var settings = $ this. data ('ininname'); // if the settings fails to be obtained, create it based on options and default. if (typeof (settings) = 'undefined') {var defaults = {propertyName: 'valu E ', onSomeEvent: function () {}} settings = $. extend ({}, defaults, options); // Save the newly created settings $ this. data ('ininname', settings);} else {/if we have obtained settings, merge it with options (this is not necessary, you can choose not to do so) settings = $. extend ({}, settings, options); // if you want to save options every time, you can add the following code: // $ this. data ('ininname', settings);} // execute code});}, destroy: function (options) {// execute code return $ (this) in each element ). each (function () {var $ This = $ (this); // run the code // Delete the data corresponding to the element $ this. removeData ('ininname') ;}, val: function (options) {// The Code passes. eq (0) is used to obtain the first element in the selector. We can also obtain its HTML content as our return value var someValue = this.eq(0).html (); // return value return someValue ;}}; $. fn. pluginName = function () {var method = arguments [0]; if (methods [method]) {method = methods [method]; arguments = Array. prototype. slice. call (arguments, 1);} else if (typeof (method) = 'Object' |! Method) {method = methods. init;} else {$. error ('method' + Method + 'does not exist on jQuery. pluginName '); return this;} return method. apply (this, arguments) ;}} (jQuery );

In the above code, I checked whether the element data exists. If the data does not exist, "options" and "default" will be merged to form a new settings, and then saved in the element with "data.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.