设计模式:使用链接+命名空间扩展jQuery对象

时间:2012-08-28 10:32:07

标签: javascript jquery oop design-patterns jquery-plugins

我需要JavaScript / jQuery设计模式的帮助。下面是一些HTML和JS代码,说明了我的工作,下面是从这些示例中推断出来的问题。

一些带有嵌套div的HTML来创建遍历场景:

    <div class="box">
        BOX 1
        <div class="nested-boxes">
            <div class="box">
                BOX 1-1
                <div class="nested-boxes">
                    <div class="box">
                        BOX 1-1-1
                    </div>
                </div>
            </div>
            <div class="box">
                BOX 1-2
            </div>
        </div>
    </div>

以下是Javacript代码:

// First I declare functions that I want to have available globally
// under a common namespace. Those functions reproduce that namespace as
// a prefix in their name to avoid conflict.
$.extend(true, window, {
    MyFunctions: {
        Boxes: {
            getBox: myfunctions_boxes_getBox
        },
        Circles: {
            // getCircle: myfunctions_circle_getCircle
        }
        // Squares....
    }
});

// I write functions which I want to use on jQuery objects as so:
function myfunctions_boxes_getNestedBoxes() {
    return this.find('.nested-boxes').first().children('.box');
}

function myfunctions_boxes_showLabel() {
    return this.find('span').first().text();   
}

// I then add those functions as new methods to my jQuery objects:
function myfunctions_boxes_getBox($element) {
    var $box = $element.closest('.box');
    $box.getParentBox = myfunctions_boxes_getParentBox;
    $box.getNestedBoxes = myfunctions_boxes_getNestedBoxes;
    $box.showLabel = myfunctions_boxes_showLabel;
    console.log('getBox',$box);
    return $box;
}

// Traversing functions call each other to make sure I retrieve a jQuery object with all
// my custom methods:
function myfunctions_boxes_getParentBox() {
    var $parent_box = myfunctions_boxes_getBox(this.closest('.box').parents('.box').first());
    console.log('getParentBox',$parent_box);
    return $parent_box;
}

现在这就是我的代码:

// I first need to call a global function:
$box = MyFunctions.Boxes.getBox($('#box-1-1'));

// Then I can start chaining my methods
$box.getParentBox().getNestedBoxes().each(function(){
    // however as soon as I use a native jQuery method, I end up with
    // a jQuery object which doesn't have my custom methods ans I need
    // to use a global function again.
    console.log($(this), MyFunctions.Boxes.getBox($(this)).showLabel());
});

A jsFiddle showing this code in action (should it help you understand what I do) is available.

Q1 :如何编写我的函数而不必在名称中重复命名空间作为前缀(例如myfunctions_boxes_),同时避免与第三方代码冲突?

每次我创建一个我想用作jQuery对象的自定义方法的新函数(例如getParentBoxgetNestedBoxes ...)我必须手动将其映射到我的一个函数(即myfunctions_boxes_getBox):

Q2 :有没有办法自动映射我的自定义方法?

以下问题可能与上述问题有关,但我更喜欢单独询问,因为我觉得它们并不完全相同

一旦我使用原生jQuery方法(例如上面例子中的each),我最终得到的jQuery对象没有我的自定义方法,我需要再次调用我的一个全局函数检索相同的对象,但附加了自定义方法。

Q3 :为我的全局函数创建一个jQuery插件以保持代码的OO性质是否有意义(参见下面的示例)?

// plugin declaration (the getBox function should be modified to make use of this)
jQuery.fn.getBox = MyFunctions.Boxes.getBox
// then my code becomes cleaner:
$('#box-1-1').getBox().getParentBox().getNestedBoxes().each(function(){
   console.log($(this).getBox().showLabel());
});

1 个答案:

答案 0 :(得分:1)

Q1:我如何编写我的函数而不必在名称中重复命名空间(例如myfunctions_boxes_),同时避免与第三方代码冲突?

现在的问题是你的函数是全局的,所以你需要将名称空间附加到它的名字以防止名称冲突(但是这仍然不能保证名称冲突的安全性)。你应该做的是将你的整个javascript代码包装在一个自我调用的函数中,例如:

(function {
    $.extend(true, window, {
        MyFunctions: {
            Boxes: {
                getBox: getBox
            }
        }
    });

    function getBox($element) {
        // Do something.
        return $element;
    }
}());

getBox函数现在是私有的,您不必担心与第三方库/等的名称冲突。

(目前仅处理第一个问题)