使用ko.computed和if语句来设置对象的可观察属性

use ko.computed with if statement to set object observable property

本文关键字:对象 观察 属性 设置 computed ko if 语句 使用      更新时间:2023-09-26

刚刚开始使用knockout和javascript。我一直在设置对象monthData的mPrice值。

function monthData(mYear, mMonth, mSS, mMs, mLimit, mPerItem, mStartingPrice) {
    var self = this;
    self.mYear= mYear;
    self.mMonth = mMonth;
    self.mSs = mSS;
    self.mMs = mMs;
    self.mTotal = mSS + mMs;
    self.mLimit = mLimit;
    self.mPerItem = mPerItem;
    self.mStartingPrice = mStartingPrice;
};

这是因为它停止了工作。如果我设置self.mPrice=0,我至少会打印出所有月份。

 self.mPrice = ko.computed(function() {
    var limit = self.mLimit;
    var perItem = self.mPerItem;
    var startingPrice = self.mStartingPrice;
    var total = self.mTotal;
    if (total <= limit) {
        return startingPrice;
    } else {
    var aboveLimit = total - limit;
    var extra = aboveLimit * perItem;
    return startingPrice + extra;
    }
});
}
function statViewModel() {
this.tak = ko.observable(100);
this.styckpris = ko.observable(10);
this.grundpris = ko.observable(500);
var self = this;
// testing with some months
self.allMonths = ko.observableArray([
    new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
    new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
    new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
    new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
    new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris)       
]);    
}

-编辑:就在我发帖后,我发现了一个失踪的超自然现象。现在我把它打印出来,但上面写着:

function d(){if(0<arguments.length){if(!d.equalityComparer||!d.equalityComparer(c,arguments[0]))d.H(),c=arguments[0],d.G();return this}b.r.Va(d);return c}NaN

Html:

<p>Tak: <input data-bind="value: tak" /></p>
<p>Styckpris: <input data-bind="value: styckpris" /></p>
<p>Grundpris: <input data-bind="value: grundpris" /></p>
<table>
<thead>
    <tr>
    <th>År</th><th>Månad</th><th>SS</th><th>MS</th><th>Total</th><th>Pris</th>
    </tr>
</thead>
<tbody data-bind="foreach: allMonths">
    <tr>
        <td><span data-bind="text: mYear"></span></td>
        <td><span data-bind="text: mMonth"></span></td>
        <td><span data-bind="text: mSs"></span></td>
        <td><span data-bind="text: mMs"></span></td>
        <td><span data-bind="text: mTotal"></span></td>
        <td><span data-bind="text: mPrice"></span></td>        
    </tr>
</tbody>
</table>

仅使用observableArray"询问"敲除来"观察"阵列功能,即push的创建、移除、移动项目等。

要"要求"knocket观察该数组中的对象,实际上需要它观察对象的特定属性。

因此,您的monthData对象应该声明observables,而不是常规/基元属性:

function monthData(mYear, mMonth, mSS, mMs, mLimit, mPerItem, mStartingPrice) {
    var self = this;
    self.mYear = mYear;
    self.mMonth = mMonth;
    self.mSs = mSS;
    self.mMs = mMs;
    self.mTotal = ko.observable( mSS + mMs );
    self.mLimit = ko.observable( mLimit );
    self.mPerItem = ko.observable( mPerItem );
    self.mStartingPrice = ko.observable( mStartingPrice );
    ...
}

注意,我只选择了最后4个作为observable,因为这些是您在computed中使用的属性。既然它们是observable,那么当它们中的任何一个发生变化时,computed将知道要重新评估。

此外,如果您希望self.mTotal自动更新(即,如果您期望self.mSsself.mSm更改(,则需要是computed而不是observable

编辑:

不要忘记使用()附加对这些变量的任何引用。您的计算机现在应该看起来像:

self.mPrice = ko.computed(function() {
    var limit = self.mLimit();
    var perItem = self.mPerItem();
    var startingPrice = self.mStartingPrice();
    var total = self.mTotal();
    if (total <= limit) {
        return startingPrice;
    } else {
        var aboveLimit = total - limit;
        var extra = aboveLimit * perItem;
        return startingPrice + extra;
    }
});

编辑2:

很抱歉没有正确阅读问题。

我没有意识到你是用takstyckprisgrundpris通过的——当我的大脑看到另一种语言时,它可能已经关闭了:p

问题

因此,当将它们传递给monthData构造函数时,您所做的就是取消引用它们。您已将值传递给可观测值,而不是传递给可观察值。通过传递该值,您的monthData构造函数,以及由此计算的mPrice,将无法看到可观察到的变化。

解决方案

将可观察性传递到构造函数中,而不取消对它们的引用。

function monthData(mYear, mMonth, mSS, mMs, mLimit, mPerItem, mStartingPrice) {
    var self = this;
    self.mYear= mYear;
    self.mMonth = mMonth;
    self.mSs = mSS;
    self.mMs = mMs;
    self.mTotal = mSS + mMs;
    /* Remember that these are observable! */
    self.mLimit = mLimit;
    self.mPerItem = mPerItem;
    self.mStartingPrice = mStartingPrice;
    self.mPrice = ko.computed(function() {
        /* So, remember to dereference them! */
        var limit = self.mLimit();
        var perItem = self.mPerItem();
        var startingPrice = self.mStartingPrice();
        var total = self.mTotal;
        if (total <= limit) {
            return startingPrice;
        } else {
            var aboveLimit = total - limit;
            var extra = aboveLimit * perItem;
            return startingPrice + extra;
        }
    });
}
function statViewModel() {
    this.tak = ko.observable(100);
    this.styckpris = ko.observable(10);
    this.grundpris = ko.observable(500);
    var self = this;
    // testing with some months
    self.allMonths = ko.observableArray([
        new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
        new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
        new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
        new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
        new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris)       
    ]);    
}

请忽略我的另一个答案。我对你原来问题中的代码和你发布的答案感到困惑。所以我的解释不清楚。因此,在这里,我将回答您的问题,而不使用答案中的任何内容

您接收时发生的错误

function d(){if(0<arguments.length){if(!d.equalityComparer||!d.equalityComparer(c,arguments[0]))d.H(),c=arguments[0],d.G();return this}b.r.Va(d);return c}NaN

可以简化为

<ko.observable>NaN

并且可以理解为:"可观察的不是数字">

这表明您正在尝试对可观察对象执行数学运算。

在您的if语句中,您有:if(total <= limit)。如果一个数字(total(小于或等于(<=(,则无法与可观测值(limit(进行比较。您必须通过像函数一样调用limit来获得它的值。

你的计算结果现在应该是这样的:

self.mPrice = ko.computed(function() {
    var limit = self.mLimit();
    var perItem = self.mPerItem();
    var startingPrice = self.mStartingPrice();
    var total = self.mTotal;
    if (total <= limit) {
        return startingPrice;
    } else {
        var aboveLimit = total - limit;
        var extra = aboveLimit * perItem;
        return startingPrice + extra;
    }
});

只有前3行需要更改-在这方面做一些小更改。没有别的。

编辑-这现在正按照我想要的工作

function monthData(mYear, mMonth, mSS, mMs, parent) {
var self = this;
self.mYear = mYear;
self.mMonth = mMonth;
self.mSs = mSS;
self.mMs = mMs;
self.mTotal = mSS + mMs;
self.mPrice = ko.computed(function () {
    var limit = parent.tak();
    var perItem = parent.styckpris();
    var startingPrice = parent.grundpris();
    var total = self.mTotal;
    if (total <= limit) {
        return startingPrice;
    } else {
        var aboveLimit = total - limit;
        var extra = aboveLimit * perItem;
        var sum = parseInt(startingPrice) + parseInt(extra);
        return sum;
    }
});
}
function statViewModel() {
var self = this;
self.tak = ko.observable(100);
self.styckpris = ko.observable(10);
self.grundpris = ko.observable(500);
// testing with some months
self.allMonths = ko.observableArray([
new monthData(2013, 1, 412, 142, self),
new monthData(2013, 2, 112, 642, self),              
new monthData(2013, 2, 100, 742, self),
new monthData(2013, 3, 6513, 69, self),
new monthData(2013, 4, 34, 211, self),
new monthData(2013, 5, 123, 435, self),
new monthData(2013, 6, 412, 142, self),
new monthData(2013, 7, 412, 142, self)
]);
}
// Activates knockout.js
ko.applyBindings(new statViewModel());