knockoutjs:级联数组(complex viewmodel)和this-pointer中的计算可观察量

时间:2014-07-02 11:43:00

标签: javascript mvvm knockout.js viewmodel

编辑: 按照建议我重构了我的viewmodel:
- 使用构造函数
- 使用子“事物”

这是小提琴:http://jsfiddle.net/drchef/hSMkc/1/

现在,计算机正在运行;)thx

但仍然有一个问题: 如果我更改食物值,则值不会返回到模型中。 元数据正在发现但食物价值却没有。 (因此总数不会更新)

P.S。:sry,我是SO的新手...我应该开始一个新问题吗?

=============================================== ============

首先,我发布了我的viewmodel;)

var vm = function() {

var self = this;    

this.activeRow = ko.observable(0);
this.user = 'hungry guy';

this.foods = ['pizza', 'burger', 'chilli'];
this.meetings = [
    {year: 2014, types: [{type: "until now", hidden: false}, {type: "forecast", hidden: false}]},
    {year: 2015, types: [{type: "forecast", hidden: false}]}
];

this.lines = ko.observableArray([
    {   id: 1,
        meta: ko.observable(
            {   shop: ko.observable('foodstore'),
                tel: ko.observable('123 456'),
                url: ko.observable('foodstore24.com')
            }),
        meetingValues: ko.observableArray([
            {   productValues: ko.observableArray([
                    {productValue: ko.observable(1)},
                    {productValue: ko.observable(0)},
                    {productValue: ko.observable(1)}]),
                total: ko.computed(function() {
                    //console.log(this.lines) -> expected: array output -> actual: undefined
                    //console.log(this.lines()) -> expected: array output -> actual: error, this.lines() ist not a function
                    //console.log(this) -> expected: this == self -> actual: this == self
                    return 0;
                }, this)
            },
            {   productValues: ko.observableArray([
                    {productValue: ko.observable(3)},
                    {productValue: ko.observable(2)},
                    {productValue: ko.observable(5)}]),
                total: ko.computed(function() {
                    return 0;
                })
            },
            {   productValues: ko.observableArray([
                    {productValue: ko.observable(2)},
                    {productValue: ko.observable(2)},
                    {productValue: ko.observable(3)}]),
                total: ko.computed(function() {
                    return 0;
                })
            }
            ])
    }
]);

};
好吧,我不得不对这个模型说一些话。

这是我复杂的knockoutjs模型。我用它来申请:

ko.applyBindings(new vm());

这个模型拥有1“线”。 this.lines是一个数组,可以容纳更多但是对于这个问题,这一行是应该的。

this.foods和this.meetings是结果表的标题。该表如下所示:

| 2014                                                              | 2015
| until now                       | forecast                        | forecast
| pizza | burger | chilli | total | pizza | burger | chilli | total | pizza | burger | chilli | total |
|     1 |      0 |      1 |     0 |     3 |      2 |      5 |     0 |     2 |      2 |      3 |     0 |

这有点难以解释但是使用表格和vm,我认为这是可以理解的;)

this.user / foods / meetings不可观察,因为它们在客户端变得无用。

正如你在vm中看到的,我的问题有一个评论。 在“总”列中,我想要三种食物的总和。 (返回比萨+汉堡+辣椒) 但这不起作用,因为“这个”不起作用。我无法访问这些值。

有人可以向我解释这个问题吗? 这个viewmodel是一个很好的做法吗?

我正在使用knockout.js.3.1.0。

谢谢你的回答 格鲁斯

P.S。:请问我,如果有人不明白这个问题;)

1 个答案:

答案 0 :(得分:1)

您有一个用于视图模型的普通JS对象。如果你这样做,那么计算和管理this相当困难。我建议也为子视图模型使用构造函数,这会使那些(和许多其他)问题和困难情况消失。 KO documentation has some info就此而言。这也可以澄清self=this的用途(您的主VM中的代码中包含它,但不要使用它)。

如果你想/坚持使用普通的JS对象,那么我建议在创建主要的observable之后添加计算。像这样:

this.lines = ko.observableArray([
    {   id: 1,
        meta: ko.observable(
            {   shop: ko.observable('foodstore'),
                tel: ko.observable('123 456'),
                url: ko.observable('foodstore24.com')
            }),
        meetingValues: ko.observableArray([
            {   productValues: ko.observableArray([
                    {productValue: ko.observable(1)},
                    {productValue: ko.observable(0)},
                    {productValue: ko.observable(1)}])
            }
            //etc
            ])
    }
]);

// See note, below code
this.lines()[0].meetingValues()[0].total = ko.computed(function() {
    //console.log(this.lines) -> expected: array output -> actual: undefined
    //console.log(this.lines()) -> expected: array output -> actual: error, this.lines() ist not a function
    //console.log(this) -> expected: this == self -> actual: this == self
    return 0;
}, this.lines()[0].meetingValues()[0]);

注意:上面的示例仅为total设置meetingValues,您必须使用循环将计算结果添加到所有this。这也是我建议使用View Models的构造函数的原因之一,因为它使管理{{1}}和计算通常更容易。