KnockoutJS:对孩子的调用功能

时间:2014-05-06 07:40:40

标签: knockout.js

以下是脚本:jsFiddle(请参阅下面的内联脚本)。

P(Page)是S(Section)对象的容器,SF(Field)对象的容器。当您单击“添加部分”时,您将获得一个新部分。同样,当单击“添加字段到节”时,您将在所选部分(currentSec)中获得一个新字段。

我不知道KO是否有直接在Section对象上调用addField()函数的语法 - 这就是我正在寻找的东西。显然,“添加字段”按钮的当前数据绑定当前不正确。

我知道我可以将addField()移动到Page对象并让它使用currentSec来做它的事情,但我想知道我是否可以保留我的结构并仍能达到相同的结果。我非常喜欢坚持我的OOP最佳实践。

HTML:

<div data-bind="foreach: secs">
    <section class="section" data-bind="click: $parent.currentSec, attr: {id: id}">
        <div data-bind="text: $data.id"/>
        <ul data-bind="foreach: $data.fields">
            <li data-bind="attr: {id: id}">New Field</li>
        </ul>
    </section>
</div>
<button data-bind="click: addSection">Add Section</button>

<div data-bind="with: currentSec">
    <button data-bind="click: addField">Add Field to Section</button>
</div>

JS:

function P() {
    this.id = 'pageId';
    this.secs = ko.observableArray();
    this.currentSec = ko.observable();
}
P.prototype.addSection = function() {
    this.secs.push(new S("section" + this.secs().length));
}

function S(sid) {
    this.id = sid;
    this.fields = ko.observableArray();
    this.currentField = ko.observable();
}
S.prototype.addField = function() {
    this.fields.push(new F("field" + this.fields().length));
}

function F(fid) {
    this.id = fid;
}

ko.applyBindings(new P());

1 个答案:

答案 0 :(得分:2)

是的,这是可能的。检查this fiddle。它基本上就是这样运行的:

<!-- ko with: currentSec -->
<button data-bind="click: addField">Add Field to Section</button>
<!-- /ko -->

它为当前部分的按钮设置context using the with binding,允许click绑定正常工作。

虽然让“添加字段”按钮出现在部分内部的某个地方,但实际上可能更有意义。在该部分中,无论如何都有正确的上下文。


我确实需要在你的代码中调整一些东西以使事情有效(我不确定它有多少是需要的,但重构这些项目有助于我进入上面提到的小提琴):

  • 我倾向于将this存储在构造函数内部的变量self中,以避免this内部函数内部addSection出现问题。
  • 有点相关,我将函数移动到构造函数本身,因此他们通过构造函数闭包访问self
  • 我添加了一些“有效”的CSS(我花了一点时间看到点击一个部分允许我“选择”它当前。
  • 我已经做到了addSection将当前部分设置为新部分(当然,这是可选的)。
  • div是自我关闭的,但这往往会造成麻烦;所以我添加了</div>结束标记。

对于手头的问题,这一切都不是很重要。为了完整起见,这是完整的工作重复:

<div id="page0" data-bind="foreach: secs">
    <section class="section" data-bind="click: $parent.currentSec, attr: {id: id}, css: { active: $parent.currentSec() == $data }">
        <div data-bind="text: $parent.id"></div>
        <ul class="connected" data-bind="foreach: fields">
            <li data-bind="attr: {id: id}, click: $parent.currentField">New Field</li>
        </ul>
    </section>
</div>
<button data-bind="click: addSection">Add Section</button>
<button data-bind="click: currentSec().addField">Add Field to Section</button>

有了这个JS:

function P() {
    var self = this;
    self.id = 'pageId';
    self.secs = ko.observableArray();
    self.currentSec = ko.observable();
    self.addSection = function() {
        var newSection = new S("section" + self.secs().length);
        self.currentSec(newSection);
        self.secs.push(newSection);
    }
}

function S(sid) {
    var self = this;
    self.id = sid;
    self.fields = ko.observableArray();
    self.currentField = ko.observable();
    self.addField = function() {
        self.fields.push(new F("field" + self.fields().length));
    };
}

function F(fid) {
    var self = this;
    self.id = fid;
}

var pvm = new P();
ko.applyBindings(pvm);