我想构建一个包含可访问方法和选项的插件,这适用于复杂的插件。 我需要在插件外部访问这些方法,因为如果有人向DOM广告,则需要更新(因此我们不需要再次运行完整的插件)。
我在过去看到有插件可以这样做,但我找不到它们,所以我不能看看它们。我还是javascript的新手,所以任何帮助都会很好。
如果我们仍然可以全局覆盖选项,那就太好了。
我想如何使用插件:
// options
$('#someid').myplugin({name: 'hello world'});
// methods(would be nice if we can use this)
$('#someid').myplugin('update');
//我的旧插件包装
;(function($, window, document, undefined){
$.fn.pluginmyPlugin = function(options) {
options = $.extend({}, $.fn.pluginmyPlugin.options, options);
return this.each(function() {
var obj = $(this);
// the code
});
};
/**
* Default settings(dont change).
* You can globally override these options
* by using $.fn.pluginName.key = 'value';
**/
$.fn.pluginmyPlugin.options = {
name: '',
...
};
})(jQuery, window, document);
更新
因此,在查看了jQuery文档之后,我构建了以下代码,如果代码有问题,请告诉我,如果它可以构建得更好......
;(function($, window, document, undefined){
var methods = {
init : function( options ) {
options = $.extend({}, $.fn.pluginmyPlugin.options, options);
return this.each(function(){
alert('yes i am the main code')
});
},
update : function( ) {
alert('updated')
}
};
$.fn.pluginmyPlugin = 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 this plugin' );
}
};
/**
* Default settings(dont change).
* You can globally override these options
* by using $.fn.pluginName.key = 'value';
**/
$.fn.pluginmyPlugin.options = {
name: 'john doe',
//....
};
})(jQuery, window, document);
答案 0 :(得分:2)
替代方案:
var Plugin = function($self, options) {
this.$self = $self;
this.options = $.extend({}, $.fn.plugin.defaults, options);
};
Plugin.prototype.display = function(){
console.debug("Plugin.display");
};
Plugin.prototype.update = function() {
console.debug("Plugin.update");
};
$.fn.plugin = function(option) {
var options = typeof option == "object" && option;
return this.each(function() {
var $this = $(this);
var $plugin = $this.data("plugin");
if(!$plugin) {
$plugin = new Plugin($this, options);
$this.data("plugin", $plugin);
}
if (typeof option == 'string') {
$plugin[option]();
} else {
$plugin.display();
}
});
};
$.fn.plugin.defaults = {
propname: "propdefault"
};
用法:
$("span").plugin({
propname: "propvalue"
});
$("span").plugin("update");
这非常类似于Twitter Bootstrap's JavaScript template。但是,它并没有完全从那里开始。我有使用.data()
的悠久历史。
不要忘记妥善包装。
答案 1 :(得分:1)
如果你想使用这样的插件:
// Init plugin
$('a').myplugin({
color: 'blue'
});
// Call the changeBG method
$('a').myplugin('changeBG')
// chaining
.each(function () {
// call the get method href()
console.log( $(this).myplugin('href') );
});
或者每个元素需要独立的插件实例:
$('a').each(function () {
$(this).myplugin();
});
你需要像这样设置你的插件:
/*
* Project:
* Description:
* Author:
* License:
*/
// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function ( $, window, document, undefined ) {
// undefined is used here as the undefined global variable in ECMAScript 3 is
// mutable (ie. it can be changed by someone else). undefined isn't really being
// passed in so we can ensure the value of it is truly undefined. In ES5, undefined
// can no longer be modified.
// window is passed through as local variable rather than global
// as this (slightly) quickens the resolution process and can be more efficiently
// minified (especially when both are regularly referenced in your plugin).
var pluginName = "myplugin",
// the name of using in .data()
dataPlugin = "plugin_" + pluginName,
// default options
defaults = {
color: "black"
};
function privateMethod () {
console.log("private method");
}
// The actual plugin constructor
function Plugin() {
/*
* Plugin instantiation
*
* You already can access element here
* using this.element
*/
this.options = $.extend( {}, defaults );
}
Plugin.prototype = {
init: function ( options ) {
// extend options ( http://api.jquery.com/jQuery.extend/ )
$.extend( this.options, options );
/*
* Place initialization logic here
*/
this.element.css( 'color', 'red' );
},
destroy: function () {
// unset Plugin data instance
this.element.data( dataPlugin, null );
},
// public get method
href: function () {
return this.element.attr( 'href' );
},
// public chaining method
changeBG: function ( color = null ) {
color = color || this.options['color'];
return this.element.each(function () {
// .css() doesn't need .each(), here just for example
$(this).css( 'background', color );
});
}
}
/*
* Plugin wrapper, preventing against multiple instantiations and
* allowing any public function to be called via the jQuery plugin,
* e.g. $(element).pluginName('functionName', arg1, arg2, ...)
*/
$.fn[pluginName] = function ( arg ) {
var args, instance;
// only allow the plugin to be instantiated once
if (!( this.data( dataPlugin ) instanceof Plugin )) {
// if no instance, create one
this.data( dataPlugin, new Plugin( this ) );
}
instance = this.data( dataPlugin );
/*
* because this boilerplate support multiple elements
* using same Plugin instance, so element should set here
*/
instance.element = this;
// Is the first parameter an object (arg), or was omitted,
// call Plugin.init( arg )
if (typeof arg === 'undefined' || typeof arg === 'object') {
if ( typeof instance['init'] === 'function' ) {
instance.init( arg );
}
// checks that the requested public method exists
} else if ( typeof arg === 'string' && typeof instance[arg] === 'function' ) {
// copy arguments & remove function name
args = Array.prototype.slice.call( arguments, 1 );
// call the method
return instance[arg].apply( instance, args );
} else {
$.error('Method ' + arg + ' does not exist on jQuery.' + pluginName);
}
};
}(jQuery, window, document));
备注:强>
参考:https://github.com/jquery-boilerplate/boilerplate/wiki/Another-extending-jQuery-boilerplate
答案 2 :(得分:0)
您是否尝试过jQuery UI Widget Factory?
有一点学习曲线,但我现在喜欢它,处理选项,默认并允许方法,让所有东西都紧紧包裹起来:)
jQuery UI Widget Factory是jQuery UI Library的一个独立组件,它提供了一种简单,面向对象的方式来创建有状态的jQuery插件。
在大多数情况下,我认为额外的开销并不值得担心。这些天我写的是coffescript,所有东西都被编译,缩小和压缩,所以这里和那里的一些额外的行没有太大的区别。我对网站速度的研究似乎表明,HTTP请求的数量是一个大问题 - 事实上,让我在这条轨道上工作的前同事适用于基于浏览器的游戏,而且速度极快。
答案 3 :(得分:0)
这是最新的样板https://github.com/techlab/jquery-plugin-boilerplate
您还可以使用create-jquery-plugin npm CLI实用程序。刚运行
npx create-jquery-plugin