【问题标题】:Multiple functions and callbacks in a custom jquery plugin?自定义 jquery 插件中的多个函数和回调?
【发布时间】:2011-09-01 16:45:40
【问题描述】:

好的,我不确定我是否以正确的方式处理这件事,但这里是......

我正在编写一个自定义 jQuery 插件来提供带有动画的下拉菜单功能(作为学习练习,所以请不要“为什么不只使用 superduperwonderplugin-x”)。

我希望能够根据用户选项(即淡入淡出、滑动、拖放等)以不同方式为菜单设置动画。目前,每个不同的动画都由插件文件中的一个单独函数处理,但我不确定如何处理回调函数(将 this 传回)!

-- 即动画只发生在对象堆栈中的最后一个元素上。

这是我的代码:

/**
 * Grizzly's Menuifier
 * 
 * @author  Chris.Leaper
 * @version a1.0
 */
(function($){
    $.fn.gmenu = function(options) {

        /* Transitions:
            - fade >> fadeIn / fadeOut
            - slide >> slideDown / slideUp
            - drop >> (different to above?)
            - bounce >> (custom config transition=? and easing=bounce)
            - stretch >> (custom config transition=? and easing=elastic)
            - fold >> (custom) drop menu @ half width then 'fold' out to full menu width
        */

        // Set the plugin default options:
        var defaults = {
            levels: '1',
            fit: 'auto',
            easing: 'linear',
            transition: 'slide',
            speed: 500
        };

        options = $.extend(defaults, options); // Merge the user options with the plugin defaults

        return this.each(function() {
            var $this = $(this);
            var opt = options;
            var container;
            var ul;

            // Setup the container elements (parent DIV/NAV and UL)!
            if( $this.is('ul') ) container = $(this).parent();
            else container = $(this);

            console.log('Container: ' + container.get(0).tagName + ' id=#' + container.attr('id') + ' class=' + container.attr('class'));

            ul = container.children('ul:first-child');

            console.log('UL: ' + ul);

            // Set the UL's position to relative:
            if($(ul).css('position') != 'relative') $(ul).css('position', 'relative');

            var offset;
            var menus = ul.children('li:has(ul)');

            console.log('List Item: ' + menus);

            menus.each(function(index, menu) {
                $menu = $(menu);

                console.log('Menu: ' + $menu);

                // Set the menu LI's position to relative (contains the absolutely positioned child UL!)
                if($menu.css('position') != 'relative') $menu.css('position', 'relative');

                // Get the menu LI's position relative to the document (it's offset)
                // -- This is only needed when positioning non-child elements
                // (i.e. ID linked menu>submenu relationships as may be used for a separated DIV based menu!!)
//              offset = menu.offest();

                // Position the submenu according to it's parent
                var submenu = $menu.children('ul');

                console.log('Submenu: ' + submenu.get(0).tagName + ' id=#' + submenu.attr('id') + ' class=' + submenu.attr('class'));

                setPosition(submenu, $menu.height());

                switch(opt.transition) {
                    case 'bounce':
                        setSMBounce(menu, opt);
                        break;
                    case 'fade':
                        setSMFade(menu, opt);
                        break;
                    case 'fold':
                        setSMFold(menu, opt);
                        break;
                    case 'stretch':
                        setSMStretch(menu, opt);
                        break;
                    case 'slide':
                    default:
                        menu = setSMSlide(menu, opt);
                }
            });

            debug(this);
        });
    };
})(jQuery);

function setPosition(submenu, height) {
    $(submenu).css({
        left: 0,
        position: 'absolute',
        top: height
    }).hide();
}

function setSMSlide(menu, opt) {
    $menu = $(menu);

    console.log('SM Slide: ' + $menu.get(0));

    $menu.first('a').mouseenter(function() {
        console.log('Start SlideDown');
        $menu.stop(true, true).slideDown(opt.speed, opt.easing);
        console.log('Stop SlideDown');
    });

    $menu.first('a').mouseleave(function() {
        console.log('Start SlideUp');
        $menu.stop(true, true).slideUp(opt.speed, opt.easing);
        console.log('Stop SlideUp');
    });
}


我认为我应该使用(相同)基于命名空间的方法来定义我的单独函数(对象文字或其他东西?),但我不确定这意味着什么或如何去做。 p>

谁能帮帮我?

【问题讨论】:

    标签: javascript jquery jquery-plugins callback


    【解决方案1】:

    要封装你的函数 setPositionsetSMSlide (在你的例子中)只需在你的插件函数中定义它们(好的地方是在定义默认变量之后。它会看起来像这样:

    var defaults = {
            levels: '1',
            fit: 'auto',
            easing: 'linear',
            transition: 'slide',
            speed: 500
        },
        setPosition = function(submenu, height) {...},
        setSMSlide = function(menu, opt) {...};
    

    由于 Javascript 中作用域的工作方式,您的 setPosition 和 setSMSlide 函数仍然可以从您的 gmenu 声明内部访问。

    【讨论】:

    • 谢谢,我试试看。这会让它们作为“$(selector).gmenu.setPosition();”访问吗?
    • 不,不会。因为您从函数(gmenu 函数)返回的是一个 jQuery 对象 - 这通常是一件好事,并且是启用链接的常见设计模式。当然,由于许多原因,许多插件不遵循该规则。我认为你最好只看一下几个插件的源代码,看看它们是如何组织的。这就是 Javascript 的美妙之处——你可以偷看和逆向工程每个脚本 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多