Summary of the five forms of jQuery plug in development
- 2020-05-10 17:39:10
- OfStack
I have done a little research on the development of the jQuery plug-in, wrote several plug-ins, and Shared a lesson about the plug-in with my team. What started out as very complex code is now much clearer when you look at it again. Here I share what I've learned to help others who have faced the same problems as me.
What am I going to do
The javascript plug-in I want should have the following characteristics
Code independence
The chain operation
Plug-in configurable
There are actionable methods that control the plug-in's lifecycle
The configuration can be cached
extensible
Conflict-free handling
Event proxy, dynamic initialization
* the following code assumes the existence of jQuery
The first form of the plug-in
Faced with this situation, we usually do this by defining function.
function pluginName($selector){
$.each($selector, function () {
$(this).css("background-color", "#ccc");
// to do something...
});
}
// pluginName(document.getElementsByClassName("demo"));
Since I am talking about jQuery plug-in development, I will now extend this code to jQuery as follows:
// IIFE( Call the function expression immediately ); [ reference http://suqing.iteye.com/blog/1981591/]
;(function ($) {
// Extend this method to jQuery.
// $.extend() Right? The method extends to $ Object, and $.fn.extend Different. Extended to $.fn.xxx After the,
// It can be when it's called $(selector).xxx()
$.fn.extend({
// The plugin name
pluginName: function () {
// Traverses the collection of matched elements
// Notice there's one here "return" , is to return the object after processing, to achieve chain operation
return this.each(function () {
// This is where you write the code to handle it
});
}
});
// pass jQuery Go to the inner scope , if window,document Use a lot of words , You can also pass it in here .
// })(jQuery, window, document, undefined);
})(jQuery, undefined);
// Call way $(".selector").pluginName().otherMethod();
But there is still a long way to go. So far only two problems have been solved
Code independence
The chain operation
Plug-in configurable
There are actionable methods that control the plug-in's lifecycle
The configuration can be cached
extensible
Conflict-free handling
Event proxy, dynamic initialization
The second form of the plug-in
Now add parameter support to the plug-in. The following code
;(function($){
$.fn.pluginName = function(options) {
// Merge parameters by" extend "Merge default and custom parameters
var args = $.extend({}, $.fn.pluginName.defaults, options);
return this.each(function() {
console.log(args.text);
// to do something...
});
};
// The default parameters
$.fn.pluginName.defaults = {
text : "hello"
};
})(jQuery);
// $(".selector").pluginName({
// text : "hello world!"
// });
It is easier to add parameter support, which solves the 1 problem
Code independence
The chain operation
Plug-in configurable
There are actionable methods that control the plug-in's lifecycle
The configuration can be cached
extensible
Conflict-free handling
Event proxy, dynamic initialization
The third form of the plug-in
Now let's add method support. I mentioned earlier that the lifecycle is controllable, which means something like adding reInit,destory, and so on to control the plug-in.
;(function($){
$.fn.pluginName = function (method) {
// If the first 1 Two parameters are strings , Just find out if the method exists , Find and call ; If it is object object , Just call init methods ;.
if (methods[method]) {
// The method is called if it exists
// apply Isn't it obj.method(arg1, arg2, arg3) Converted to method(obj, [arg1, arg2, arg3]) The process of .
// Array.prototype.slice.call(arguments, 1) Is to convert the method's arguments to an array .
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
// If the parameter passed in is "{...}", It's considered an initialization operation .
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.pluginName');
}
};
// Do not extend the method in $.fn.pluginName on . Build one inside the closure "methods" To save the method , Similar common methods .
var methods = {
/**
* Initialization method
* @param _options
* @return {*}
*/
init : function (_options) {
return this.each(function () {
var $this = $(this);
var args = $.extend({}, $.fn.pluginName.defaults, _options);
// ...
})
},
publicMethod : function(){
private_methods.demoMethod();
}
};
// Private methods
function private_methods = {
demoMethod : function(){}
}
// The default parameters
$.fn.pluginName.defaults = {
};
})(jQuery);
// Call way
// $("div").pluginName({...}); // Initialize the
// $("div").pluginName("publicMethod"); // A method is called
Problem number one
Code independence
The chain operation
Plug-in configurable
There are actionable methods that control the plug-in's lifecycle
The configuration can be cached
extensible
Conflict-free handling
Event proxy, dynamic initialization
The fourth form of the plug-in
Plug-in modifications in the third form can already address the needs of most plug-ins. Keep upgrading.
The plug-in in the fourth form is based on the code of javascript framework designed by situ zhengmei. A little bit of object-oriented knowledge.
(function ($) {
var Plugin = function (element, options) {
this.element = element;
this.options = options;
};
Plugin.prototype = {
create: function () {
console.log(this.element);
console.log(this.options);
}
};
$.fn.pluginName = function (options) {
// Consolidation parameters
return this.each(function () {
// This is where you write the code to handle it
var ui = $._data(this, "pluginName");
// If the element is not initialized ( It could be a newly added element ), I'm going to initialize it .
if (!ui) {
var opts = $.extend(true, {}, $.fn.pluginName.defaults, typeof options === "object" ? options : {});
ui = new Plugin(this, opts);
// Cache plug-in
$._data(this, "pluginName", ui);
}
// A method is called
if (typeof options === "string" && typeof ui[options] == "function") {
// Method to execute the plug-in
ui[options].apply(ui, args);
}
});
};
$.fn.pluginName.defaults = {};
})(jQuery);
// How and before the call 1 The sample.
Here especially to mention the cache this thing, plug-in used more, feel this is really a good thing.
In traditional object-oriented plug-in development, you would declare at least one variable to hold it, but none of the jQuery plug-ins I've written so far have it, and it's a pain to use. Since the initial plug-in is cached, it is much easier. You can fetch the object with the code $("#target").data("pluginName"). Let's see if there are any problems left
Code independence
The chain operation
Plug-in configurable
There are actionable methods that control the plug-in's lifecycle
The configuration can be cached
extensible
Conflict-free handling
Event proxy, dynamic initialization
The fifth form of the plug-in
See if the above code is a little dizzy, if so, take a short break, come back later, the following code is more exciting. The last one is quite comprehensive. The scheme comes from Bootstrap, and the following code takes the button plug-in of Bootstrap as an example.
!function ($) {
// ecma262v5 The new things , Enforce strict coding .
"use strict";
// BUTTON PUBLIC CLASS DEFINITION
// ==============================
var Button = function (element, options) {
this.$element = $(element);
this.options = $.extend({}, Button.DEFAULTS, options);
};
Button.DEFAULTS = {
loadingText: 'loading...'
};
Button.prototype.setState = function (state) {
// ...
};
Button.prototype.toggle = function () {
// ...
};
// BUTTON PLUGIN DEFINITION
// ========================
var old = $.fn.button; // Here, $.fn.button It may be a plug-in that has been defined before and is used here for conflict-free handling.
$.fn.button = function (option) {
return this.each(function () {
var $this = $(this);
// The basis for determining whether or not initialization has been performed
var data = $this.data('bs.button');
var options = typeof option == 'object' && option;
// If it's not initialized , I'm going to initialize it
if (!data) $this.data('bs.button', (data = new Button(this, options)));
if (option == 'toggle') data.toggle();
else if (option) data.setState(option)
})
};
// 1. Exposure to the name of the class , You can use this to customize extensions for your plug-in
$.fn.button.Constructor = Button;
// Extended way
// Set up the : $.fn.button.Constructor.newMethod = function(){}
// use : $btn.button("newMethod");
// 2. Conflict-free handling
$.fn.button.noConflict = function () {
$.fn.button = old;
return this
};
// 3. The event agent , Intelligent initialization
$(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {
var $btn = $(e.target);
// Find the object to initialize
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn');
// Call method directly , If it's not initialized , Internally, it initializes first
$btn.button('toggle');
e.preventDefault();
});
}(jQuery);
Let's see if there are any problems left
Code independence
The chain operation
Plug-in configurable
There are actionable methods that control the plug-in's lifecycle
The configuration can be cached
extensible
Conflict-free handling
Event proxy, dynamic initialization
supplement
Today's plug-ins require a lot of flexibility, such as the ability to accommodate both jQuery and Zepto, or the need to support the AMD or CMD specifications.
jQuery and Zepto are supported
if (window.jQuery || window.Zepto) {
(function ($) {
// plugin code...
})(window.jQuery || window.Zepto);
}
Middleware support, node
if (typeof(module) !== 'undefined')
{
module.exports = pluginName;
}
requirejs(AMD) support
if (typeof define === 'function' && define.amd) {
define([], function () {
'use strict';
return pluginName;
});
}
seajs(CMD) support
if (typeof define === 'function') {
define([], function () {
'use strict';
return pluginName;
});
}
Call ~, the problem has been solved, the code if there is not understand the place can see more. It doesn't matter if you don't understand the last few. In actual development, the first few are enough. It should be stressed that it is not better to write in a more advanced way, but to make a reasonable choice based on the requirements of your own project.
Well, that's the end of today's summary, if you have a better way of plug-in development, please let me know 1. I hope you enjoyed this article.