【问题标题】:How to notify parent of a change如何通知家长更改
【发布时间】:2012-06-03 22:23:52
【问题描述】:

我正在使用 KnockoutJS,我想知道 observableArray 中的可观察对象可以通知父级更改的方法。这是一个例子:

http://jsfiddle.net/paragnair/CEEZ5/

HTML:

<h1 id="heading"> <text data-bind="text:childrenCount"></text> Fields selected</h1>
<table id="form">
<tbody data-bind="foreach:children">
    <tr>
        <td data-bind="text:name"></td>
        <td><input type="checkbox" data-bind="checked:isSelected"/></td>
    </tr>
</tbody>
</table>

<a href="#" id="btn-add">Add More Fields</a>​

Javascript:

var Child = function(name) {
    var self = this;
    self.name = ko.observable(name);
    self.isSelected = ko.observable(false);
},
    Parent = function() {
        var self = this;
        self.children = ko.observableArray([
            new Child('One'),
            new Child('Two'),
            new Child('Three')
            ]);
        self.children.subscribe(function(children) {
            header.childrenCount($.map(children, function(a) {                
                return a.isSelected() ? 1 : null;
            }).length);
        });
    },
    header = {
        childrenCount: ko.observable(0)
    };

var parentModel = new Parent(),
    extra = parentModel.children().length;
ko.applyBindings(parentModel, $('#form')[0]);
ko.applyBindings(header, $('#heading')[0]);

function setHeading(childrenCount) {
    header.childrenCount(childrenCount);
}

$(document).ready(function() {
    $('#btn-add').click(function() {
        extra++;
        parentModel.children.push(new Child('Extra ' + extra));
        return false;
    });
});​

在上面的示例中,我想显示带有所选字段数的标题。我对observableArray 有一个subscribe 事件,但只有在从数组中添加或删除某些内容时才会触发,因此当用户实际选中字段列表中的复选框时,不会触发该事件。实现此目的的一种方法是在复选框上添加一个 onchange 事件以调用父级上的一个方法,该方法又调用一些外部方法来更新header 对象上的childrenCount。有更好的方法吗?

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    我认为您可以采用不同的方式解决此问题,同时消除不必要的复杂情况。您不需要将模型分成单独的 applyBindings 调用。事实上,除非绝对必要,否则不建议这样做,因为它会增加复杂性,如果您不小心可能会导致双重绑定。

    其次,如果您的标题是您的 parentModels 子项的结果,那么它确实应该是同一模型的一部分,在编写 KO 模型时可以并且应该应用 OOP 原则。这是一开始就选择使用 KO 的优势。

    以下是我将如何解决您的问题。

    http://jsfiddle.net/madcapnmckay/edJyp/

    var Child = function(name) {
        var self = this;
        self.name = ko.observable(name);
        self.isSelected = ko.observable(false);
    },
    Parent = function() {
        var self = this;
        self.children = ko.observableArray([
            new Child('One'),
            new Child('Two'),
            new Child('Three')
            ]);
    
        this.childrenCount = ko.computed(function() {
            var count = 0;
            ko.utils.arrayForEach(self.children(), function (child) {
                if (child.isSelected()) {
                    count++;
                }
            });
            return count;
        });
    
        this.addMore = function () {
            self.children.push(new Child("Extra " + (self.children().length + 1)));
        };
    };
    
    var ViewModel = function () {
        var self = this;
        this.parentModel = new Parent();  
    };
    
    ko.applyBindings(new ViewModel());
    

    请注意,ViewModel 类是多余的,但我假设您拥有的功能比此处显示的更多,这些功能将被标记到此。

    顺便说一句,您为什么觉得需要在按钮上使用 jquery 点击处理程序?我经常看到这个错误,并且想知道文档中的哪些内容会引导您走上这条路?这也可以也应该移到您的 viewModel 上,我在示例中已经这样做了。

    希望这会有所帮助。

    【讨论】:

    • 不幸的是,我的应用程序的设计方式,我必须将 applyBindings 分开。因此,每当更新数组中的 obserbale 对象的值时,我需要一种方法来调用外部函数。而对于按钮上的点击处理程序,这只是一个例子,这不是我的实际项目。
    【解决方案2】:

    最后我没有使用订阅,而是在data-bind 上使用了event,它又调用了外部函数setHeading。这是更新的小提琴:http://jsfiddle.net/paragnair/CEEZ5/5/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-03
      • 2022-09-28
      • 2022-06-14
      相关资源
      最近更新 更多