带有方法和全局回调的 jQuery 插件

Posted

技术标签:

【中文标题】带有方法和全局回调的 jQuery 插件【英文标题】:jQuery plugin with methods & global callbacks 【发布时间】:2012-11-09 16:07:39 【问题描述】:

我想创建一个同时具有方法和回调的 jQuery 插件,方法可以工作,但我无法让回调工作,回调的范围让我感到困惑,

(function($)

    var methods = 

        create: function(options) 

            var defaults = 
                width: 320,
                height: 240,
                background: '#000',
                onstop: function()
            ;

            var options = $.extend(defaults, options);

            return $(this).each(function(i) 

                console.log('create');

            );

        ,
        stop: function(options) 

            var defaults = 
                onstop: function()
            ;

            var options = $.extend(defaults, options);

            return $(this).each(function(i) 

                console.log('stop');
                options.onstop.call();

            );
        
    ;

    $.fn.myplugin = function(option) 

        if (methods[option]) 
            return methods[option].apply( this, Array.prototype.slice.call(arguments, 1));
         else if (typeof option === 'object' || ! option) 
            return methods.create.apply(this, arguments);
         else 
            $.error('Method ' +  option + ' does not exist in jQuery.plugin');
            
    ;

)(jQuery);

所以在<script>:

$(document).ready(function()

    $('#start').click( function()
        $('#myvideo').myplugin('create',  onstop: function() console.log('on stop');  );
    );

    $('#stop').click( function()
        $('#myvideo').myplugin('stop');
    );

);

基本上,我似乎想让 onstop: function() 对插件全局化

/* ======== 更新代码(见 cmets) ======== */

(function($)


    var callbacks = 
        onready: $.Callbacks("once memory unique").add(function() 
            //console.log('onready');
        ),
        ondeny: $.Callbacks("unique").add(function() 
            //console.log('ondeny');
        ),
        onerror: $.Callbacks("unique").add(function() 
            //console.log('onerror');
        ),
        onstop: $.Callbacks("unique").add(function() 
            //console.log('onstop');
        )
    ;

    var methods = 

        construct: function()
        ,
        create: function(options) 

            var defaults = 
                width: 320,
                height: 240,
                background: '#000',
                onready: function(),
                onstop: function()
            ;

            var options = $.extend(defaults, options);

            return this.each(function(i, elements) 

                for (var prop in options) 
                    if (prop in callbacks) 
                        callbacks[prop].add(options.prop);
                    
                

                callbacks.onready.fire();

            );

        ,
        stop: function() 

            return this.each(function(i, elements) 
                callbacks.onstop.fire();
            );
        
    ;

    $.fn.myplugin = function(option) 

        if (methods[option]) 
            return methods[option].apply( this, Array.prototype.slice.call(arguments, 1));
         else if (typeof option === 'object' || ! option) 
            return methods.construct.apply(this, arguments);
         else 
            $.error('Method ' +  option + ' does not exist in jQuery.plugin');
            
    ;

)(jQuery);

【问题讨论】:

回调应该由插件的用户设置,不是吗? 我想让它们作为选项访问 【参考方案1】:

我建议使用一些成熟的 jQuery.Callbacks 对象:

var callbacks = 
    onready: $.Callbacks("once memory unique").add(function() 
        console.log('ready');
    ),
    ondeny: $.Callbacks("unique").add(function() 
        console.log('deny');
    ),
    onerror: $.Callbacks("unique").add(function() 
        console.log('error');
    ),
    onstop: $.Callbacks("unique").add(function() 
        console.log('stop');
    )
;

现在,当您获得一些新选项时,您可以这样做

for (var prop in options)
    if (prop in callbacks)
        callbacks[prop].add(options[prop]);

然后调用它们就行了

callbacks.onstop.fire(/*args*/);

或者,如果您关心回调的上下文,请使用fireWith

【讨论】:

起初这似乎有效,但我忘记了我还有另一个 console.log(),我很好奇“曾经的记忆独特”和“独特”等是做什么的?我添加了回调,例如 onready: $.Callbacks("onready").add(function() console.log('onready'); ),我还在 'create' 方法中将它们添加为选项,但它们目前似乎没有开火。还在纠结... 好吧,我发现了“独特”之类的。将代码更新为我现在拥有的代码,仍然没有触发回调。 $('#start').click( function() $('#myvideo').myplugin('create', onready: function() console.log('!on ready!'); , onstop: function() console.log('!on stop!'); ); );这不记录 糟糕,修复了循环中向回调添加函数的小问题。顺便说一句,我不确定您是否要分离应用插件的每个元素的回调,因为那时您不能使用静态 callbacks 对象。在.each-loop 中添加回调也没什么用,因为它们只会在没有unique 标志的情况下再次添加。【参考方案2】:

我使用 globalOptions 变量将插件初始化选项存储为全局,

这是用于测试和用作模板的两个文件。

jquery.plugin.js (函数($)

    var pluginName = 'myPlugin';

    var globalOptions = '';

    var methods = 

        create: function(options) 

            var defaults = 
                backgroundColor: '#000',
                color: '#fff',
                oncreate: function(),
                onchangecolor: function(),
                onloadpage: function(page)
            ;

            globalOptions = $.extend(defaults, options);

            return $(this).each(function(i, elements) 

                $(elements).data('globalOptions', globalOptions);

                globalOptions.oncreate();

            );

        ,
        changeColor: function()

            return $(this).each(function(i, elements) 

                globalOptions = $(elements).data('globalOptions');
                if (!globalOptions)  $.error('Error: ' + pluginName + ' has not been initialized yet'); return false; 

                $(this).css('background-color', globalOptions.backgroundColor);
                $(this).css('color', globalOptions.color);

                globalOptions.onchangecolor();

            );
        ,
        loadPage: function(options)

            return $(this).each(function(i, elements) 

                globalOptions = $(elements).data('globalOptions');
                if (!globalOptions)  $.error('Error: ' + pluginName + ' has not been initialized yet'); return false; 

                globalOptions.onloadpage(options.page);
                location.href = options.page;

            );
        

    ;

    $.fn.myPlugin = function(option) 

        if (methods[option]) 
            return methods[option].apply(this, Array.prototype.slice.call(arguments, 1));
         else if (typeof option === 'object' || ! option) 
            return methods.create.apply(this, arguments);
         else 
            $.error('Error: Method "' + option + '" does not exist in ' + pluginName);
            return false;
            
    ;

)(jQuery); 

index.html

<!doctype html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Example</title>
        <script src="jquery.min.js"></script>
        <script src="jquery.plugin.js"></script>
        <script>
$(document).ready(function() 

    var myElement = $('.container').myPlugin(
        color: '#555',
        backgroundColor: '#ddd',
        oncreate: function()
            console.log('Callback: create');
        ,
        onchangecolor: function()
            console.log('Callback: onchangecolor');
        ,
        onloadpage: function(page)
            console.log('Callback: onloadpage = '+page);
        
    );

    $('.color').click(function(event)
        myElement.myPlugin('changeColor');
    );

    $('.page').click(function(event)
        myElement.myPlugin('loadPage',  page: '#test' );
    );

);
        </script>
    </head>
    <body>
        <div class="container">
            <button class="color">changeColor</button> <button class="page">loadPage</button>
        </div>
    </body>
</html>

如果有人有更好的方法和添加“私有”方法的方法,请分享。 :)

【讨论】:

以上是关于带有方法和全局回调的 jQuery 插件的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript之jQuery-9 jQuery 开发插件(添加新全局函数添加jQuery对象方法添加新简写方法方法参数)

webpack全局引入jquery的方法

jquery.Ajax回调成功后数据赋值给全局变量的问题

jQuery插件开发全解析

jQuery插件开发全解析

转:jQuery插件开发全解析