无法获得正确的敲除绑定上下文

时间:2013-12-08 11:06:16

标签: javascript knockout.js

我有以下javascript来执行我的敲除绑定。

var context = this;

var viewModel = {
    lineitems: [{
        quantity: ko.observable(1),
        title: 'bar',
        description: 'foo',
        price: ko.observable(10),
        total: ko.observable(10),
        formattedTotal: ko.computed({
        read: function () { 
            return '$' + this.price().toFixed(2);
        },
        write: function (value) { 
            value = parseFloat(value.replace(/[^\.\d]/g, ""));
            this.price(isNaN(value) ? 0 : value);
        } 
       })
    }]
};

ko.applyBindings(viewModel);

哪个绑定符合预期,但是当我应用formattedTotal时,我收到以下javascript错误。

Uncaught TypeError: Object [object global] has no method 'price'

我已尝试对语法进行一些更改,但我似乎无法做到正确,我哪里出错?

2 个答案:

答案 0 :(得分:1)

通常,在JavaScript中使用this并不是最佳选择。尤其是Knockout。你永远不知道执行期间this会是什么。

所以我建议这样写:

function LineItem(_quantity, _title, _description, _price) {
    var self = this;

    self.quantity = ko.observable(_quantity);
    self.title = ko.observable(_title);
    self.description = ko.observable(_description);
    self.price = ko.observable(_price);

    self.total = ko.computed(function () {
        return self.price() * self.quantity();
    }, self);

    self.formattedTotal = ko.computed(function () {
        return '$' + self.total().toFixed(2);
    }, self);
};

var viewModel = {
    lineItems: [
    new LineItem(10, 'Some Item', 'Some description', 200),
    new LineItem(5, 'Something else', 'Some other desc', 100)
]
};

ko.applyBindings(viewModel);

您可以阅读有关self=this模式here.

的一些讨论

答案 1 :(得分:1)

问题出在您的formattedTotal方法中:范围 - this - 不是您的viewModel。试试这个:

var viewModel = {
    lineitems: [{
        quantity: ko.observable(1),
        title: 'bar',
        description: 'foo',
        price: ko.observable(10),
        total: ko.observable(10),
        formattedTotal: ko.computed({
        read: function () { 
            return '$' + viewModel.lineitems.price().toFixed(2);
        },
        write: function (value) { 
            value = parseFloat(value.replace(/[^\.\d]/g, ""));
            viewModel.lineitems.price(isNaN(value) ? 0 : value);
        } 
       })
    }]
};

考虑为viewmodels使用构造函数而不是对象文字;这使得处理范围问题更容易和更清洁。有关示例,请参阅this answer