2

我正在尝试在与 HTML 元素密切相关的 JavaScript 中构建干净的面向对象代码。

我试图解决的情况是一个页面,其中给出了多个建议。每个建议都有几个选项,每个选项都有一个按钮来激活它。HTML 的简化片段如下所示:

<div class="row suggestion">
    <div class="span6">
        <ul>
            <li data-id="1">
                <span>Option 1</span>
                <span><a class="btn btn-mini" href="#">pick me</a></span>
            </li>
            <li data-id="2">
                <span>Option 2</span>
                <span><a class="btn btn-mini" href="#">pick me</a></span>
            </li>
        </ul>
    </div>
    <div class="span6">
       <button>Save</button>
    </div>
</div>

我知道如何在不使用对象的情况下编写脚本,但是因为我想为建议添加更多功能,所以我想采用干净的 OO 方法。我希望你知道 OO 的好处并接受我的选择

到目前为止我尝试过的看起来像这样:

$(document).ready(function(){
    var suggestions = [];

    $('.row.suggestion').each(function(){
        suggestions.push(
            new Suggestion($(this))
        );
    });
});

function Suggestion($el){
    var options = new Array();

    $el.find('a').each(function(){
        options.push(new Button($(this)));
    })
}
Suggestion.prototype = {
    childChange : function(){
        // do some checks;
    }
}

function Button($el){
    this.$el = $el;
    this.id = $el.parents('li').data('id');
    $el.click(this.onclick);
}
Button.prototype = {
    checked : false,
    $el : null,
    id : 0,
    onclick : function(){
        // set this button active
        // notify my parent suggestion that i've changed
    }
}

它可以按预期工作直到 onclick 功能。当它被触发时,该功能启动,但范围发生了变化。我以为我可以访问该对象,但我仅限于单击元素的 jQuery 实例的范围。

我有一些想法,但他们都有自己的警告:

到目前为止,我还没有找到一个已知的 JavaScript 面向对象编程的解决方案,它与页面上的元素密切相关。我发现的所有 OO JS 示例都没有元素作为起点。欢迎所有建议。

4

2 回答 2

1

您可以$.proxy()为此使用:

$el.click($.proxy(this.onclick, this));

然后onclick将在您的Button对象的上下文中调用。

于 2013-04-27T08:51:38.107 回答
1

首先,我会选择一种更易于维护的 OO 模式。

然后,要与元素相关,您只需将它们设为实例属性。

var myApp = {};
myApp.dom = {};
myApp.dom.Suggestion = function(options) {
   this.container = document.createElement("option");
   this.options = [];
   for (var i = 0, len = options.length; i < len; i++) {
       this.options[i] = document.createElement("option");
       this.options[i].setAttribute("value", options[i]);
       this.options[i].addEventListener("change", this.change.bind(this), false);
       this.container.appendChild(this.options[i]);
   };
};
// now you already have two properties, the suggestion container and the options.
myApp.dom.Suggestion.prototype.change = function(event) {
    var currentOption = event.target;
};
myApp.dom.Suggestion.prototype.decorateElement = function(parent) {
   try {
      parent.appendChild(this.container);
   } catch (DOMException) {
      console.log("Specify a parent element");
   };
};
// now you have instance references to all your properties.

您真正需要的只是元素之上的抽象。ASuggestion会有select一个容器,如果你创建一个Option类,它会有option一个容器,等等。然后添加你需要的所有功能。重要的部分是在正确的范围内调用事件,这可以通过Function.prototype.bind.

如果你喜欢这种方法,那么看看 Google Closure Library,一切都是以这种风格构建的。诚然,它是一个包含大量工具的大型库,并且在没有工具的情况下使用该库并不是很有效。

如果您只想快速完成工作,请使用 jQuery 和 proxy.

this.container.change($.proxy(this.change, this));

并将原生的 JS 方法替换为 jQuery 方法,保证跨浏览器的兼容性。

于 2013-04-27T08:56:52.057 回答