【问题标题】:KnockoutJS observable properties in observable array not tracked未跟踪可观察数组中的 KnockoutJS 可观察属性
【发布时间】:2015-11-30 15:13:11
【问题描述】:

这是一个模型:

        function DiscountItem(minDays, percent) {
            var self = this;
            self.minDays = ko.observable(minDays);
            self.discount = ko.observable(percent);
        }

        function TableItem(name, from, to, price, hasDiscount) {
            var self = this;
            self.name = name;
            self.from = from;
            self.to = to;
            self.price = price;
            self.discount = hasDiscount;
        }

        function AppViewModel() {
            var self = this;

            self.discounts = ko.observableArray([
                new DiscountItem(12, 4),
                new DiscountItem(20, 6)
            ]);

            self.table = ko.observableArray([
                new TableItem("first", "20.03","3.04", 400, 1),
                new TableItem("second", "11.04","4.05", 600, 0)
            ]);

            self.addDiscount = function() {
                self.discounts.push(new DiscountItem(0, 0));
            }

            self.removeDiscount = function() {
                self.discounts.remove(this);
            }

            self.addPeriod = function() {
                self.table.push(new TableItem("","","", 0, 1));
            }

            self.removePeriod = function() {
                self.table.remove(this);
            }

            self.pricing = ko.computed(function() {
                return JSON.stringify({
                    durationDiscount : self.discounts(),
                    periods: self.table()
                })
            }, self);
        }

这就是我需要的:

每次我更改可观察属性之一或在 observableArray 中添加新项目时,我都需要使用来自 self.discounts 和 self.table 的数据的 JSON 表示填充其他输入

类似的东西

{"durationDiscount":[{"minDays":12,"discount":4},{"minDays":20,"discount":6}],"periods":[{"name":"first","from":"20.03","to":"3.04","price":400,"discount":1},{"name":"second","from":"11.04","to":"4.05","price":600,"discount":0}]}

如果我删除模型属性上的 ko.observable() 一切正常,但我需要跟踪它们。

如果我添加 ko.observable(),ko.computed 中的 self.discounts 会返回空数组

【问题讨论】:

  • 这是一个很好的问题,但很难理解这个问题。您能否使用jsfiddle.net 或此处的代码 sn-p 重现该问题。
  • 当然可以。我创建了一个简化版本,以便更好地理解问题jsfiddle.net/cbqenwy9 每当我更改值或添加新行时,我都需要更新 textarea 中的 JSON 数据

标签: knockout.js


【解决方案1】:

observableArray 实际上不提供有关项目更改的通知,请参阅documentation note。因此,您有两个选择 - 订阅项目的更改或在您的计算范围内调用项目的可观察对象。我更喜欢这样的第二个

self.pricing = ko.computed(function() {
         return ko.toJSON({
                durationDiscount : ko.utils.arrayMap(this.discounts(), 
function(item){ 
  return new DiscountItem(ko.unwrap(item.discount), ko.unwrap(item.minDays)); })
               })}, self);

看我的叉子http://jsfiddle.net/xv62vs6c

【讨论】:

    【解决方案2】:

    我认为唯一的问题是,当这些属性是可观察的时,您不会在 pricing 属性中获得它们的 。试试这个:

    self.pricing = ko.computed(function() {
        return JSON.stringify({
            durationDiscount : self.discounts().map(function(x){ 
                  return { minDays: x.minDays(), discount: x.discount() }
            }),
            periods: self.table()
        })
    }, self);
    

    function DiscountItem(minDays, percent) {
        var self = this;
        self.minDays = ko.observable(minDays);
        self.discount = ko.observable(percent);
    }
    
    function TableItem(name, from, to, price, hasDiscount) {
        var self = this;
        self.name = name;
        self.from = from;
        self.to = to;
        self.price = price;
        self.discount = hasDiscount;
    }
    
    function AppViewModel() {
        var self = this;
    
        self.discounts = ko.observableArray([
            new DiscountItem(12, 4),
            new DiscountItem(20, 6)
        ]);
    
        self.table = ko.observableArray([
            new TableItem("first", "20.03","3.04", 400, 1),
            new TableItem("second", "11.04","4.05", 600, 0)
        ]);
    
        self.addDiscount = function() {
            self.discounts.push(new DiscountItem(0, 0));
        }
    
        self.removeDiscount = function() {
            self.discounts.remove(this);
        }
    
        self.addPeriod = function() {
            self.table.push(new TableItem("","","", 0, 1));
        }
    
        self.removePeriod = function() {
            self.table.remove(this);
        }
    
        self.pricing = ko.computed(function() {
            return JSON.stringify({
                durationDiscount : self.discounts().map(function(x){ return { minDays: x.minDays(), discount: x.discount() }}),
                periods: self.table()
            })
        }, self);
    }
    
    ko.applyBindings(new AppViewModel());
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <div data-bind="foreach: discounts">
        <div>
            <span><input data-bind="value: minDays" /></span>
            <span><input data-bind="value: discount" /></span>
        </div>
    </div>
    
    <pre data-bind="text: pricing"></pre>

    【讨论】:

    • 还有一个问题,如果其中一个字段是日期字段并填充了 jquery-daetimepicker,那么观察也不起作用。
    猜你喜欢
    • 2012-04-20
    • 2011-06-13
    • 2017-11-25
    • 2015-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多