knockout js嵌套模型与继承数据

时间:2014-09-15 06:53:00

标签: javascript knockout.js coding-style

我正在制作淘汰赛的js模特。理想情况下,我希望每个页面都有子视图。该模型看起来像这样:

function viewModel()
{
    var self = this;
    self.people = ko.observableArray([{"name":"Alice", parent:"Bill"},{"name":"Bill":"parent":"Candy"},{"name":"Candy","parent":""}]);

    function kidsModel()
    {
         var self = this;
         self.kids = ko.utils.arrayFilter(people, function(person) {
              return person.parent != "";
          }); 
    }

    function parentsModel()
    {
         var self = this;
         self.parents = ko.utils.arrayFilter(
                            ko.utils.arrayMap(people, function(person){
                                return person.parent;
                           })
                        , function(person) {
                              return person.parent != "";
                        });
    }
}

关键组件是我可以使用子视图对代码进行分段,并共享通过根视图过滤的数据。我已经找到了很多关于在淘汰赛中设置好的子视图的信息,但没有找到以利用淘汰赛的方式在它们之间过滤数据的信息。

1 个答案:

答案 0 :(得分:2)

您可以将observableArray作为参数传递给子视图模型。例如(它的代码太多了,但它非常简单):

// Person model
function Person(name, parent) {
    this.name = ko.observable(name);
    this.parent = ko.observable(parent);
}
// Template model, for sub views
function Template(name, data, isReady) {
    this.name = ko.observable(name);
    this.data = ko.observable(data);
    this.isReady = ko.observable(isReady);
}
// Main view model, controls templates
function ViewModel()
{
    var self = this;
    self.people = ko.observableArray([new Person("Alice", "Bill"), new Person("Bill","Candy"),new Person("Candy", "")]);

    // working with templates
    self.template = new Template('kidsTemplate', new KidsModel(self.people), true);

    self.showKids = function() {
        self.template.isReady(false);
        self.template.name('kidsTemplate');
        self.template.data(new KidsModel(self.people));
        self.template.isReady(true);
    };
    self.showParents = function() {
        self.template.isReady(false);
        self.template.name('parentsTemplate');
        self.template.data(new ParentsModel(self.people));
        self.template.isReady(true);
    };
}
// Sub-view model for Kids, takes observable array as a parameter
function KidsModel(people)
{
    var self = this;
    self.kids = ko.computed(function() {
        return ko.utils.arrayFilter(people(), function(person) {
            return person.parent() !== "";
        });
    });
    self.newKidName = ko.observable('John');
    self.newKidParentName = ko.observable('Peter');
    self.addKid = function() {
        people.push(new Person(self.newKidName(), self.newKidParentName()));
    };
}
// Sub-view model for Parents, takes observable array as a parameter
function ParentsModel(people)
{
    var self = this;
    self.parents = ko.computed(function() {
        return ko.utils.arrayFilter(
            ko.utils.arrayMap(people(), function(person){
                return person.parent();
            }),
            function(person) {
                return person;
                //return person.parent !== "";
            });
    });
}

标记是这样的:

<button data-bind="click: showKids">Show kids</button>
<button data-bind="click: showParents">Show parents</button>
<div data-bind="template: { name: template.name, data: template.data, if: template.isReady}"></div>

<script type="text/html" id="kidsTemplate">
    <!-- ko foreach: kids -->
    <div>
        Kid's Name: <b data-bind="text: name"></b>, Kid's Parent: <b data-bind="text: parent"></b>
    </div>
    <!-- /ko -->
    <div>
        New kid name: <input type="text" data-bind="value: newKidName" />, parent name: <input type="text" data-bind="value: newKidParentName" />
        <button data-bind="click: addKid">Add kid</button>
    </div>    
</script>
<script type="text/html" id="parentsTemplate">
    <!-- ko foreach: parents -->
    <div>
        Parent's Name: <b data-bind="text: $data"></b>
    </div>
    <!-- /ko -->
</script>

Working demo.