如何在 Knockout.js 中嵌套对象

Posted

技术标签:

【中文标题】如何在 Knockout.js 中嵌套对象【英文标题】:How to nest object in Knockout.js 【发布时间】:2021-06-21 04:45:57 【问题描述】:

在 Knockout.js 中,将对象嵌套在数组中的最佳方法是什么?

我试图有一个按一组课程标题排序的可观察对象,并且在里面会有不同的课程提供给具有相同组属性(课程代码)的学生。

这是我的sn-p

function course(_id, _code, _title, _campus) 
    var self = this;
    this.id = ko.observable(_id);
    this.courseCode = ko.observable(_code);
    this.courseTitle = ko.observable(_title);
    this.coursecampus = ko.observable(_campus);


function gpCourseProperties(_code, _isHidden) 
    var self = this;
    this.gpCode = ko.observable(_code);
    this.hide = ko.observable(_isHidden);
    this.courses = ko.observableArray();

    this.addCourse = function (_id, _courseCode, _courseTitle, _courseCampus) 
        self.courses.push(new course(_id, _courseCode, _courseTitle, _courseCampus));
    

    this.switchMutated = function (code) 
        self.hide(!self.hide());
    ;
    this.switchText = ko.computed(function () 
        if (self.hide() == true) 
            return '+'
        
        return '-';
    , this);


function ViewModel() 
    var self = this;
    this.gpCourseProp = ko.observableArray();

self.gpCourseProp.push(new gpCourseProperties("MATH1030", true));
self.gpCourseProp.push(new gpCourseProperties("MATH1006", true));
self.gpCourseProp.push(new gpCourseProperties("MATH1046", true));

    for (i = 0; i < self.gpCourseProp().length; i++) 
    if (self.gpCourseProp()[i].gpCode == "MATH1030") 
        self.gpCourseProp()[i].addCourse(new course("1", "MATH1030", "Calculus", "City1"));
        self.gpCourseProp()[i].addCourse(new course("2", "MATH1030", "Calculus", "City2"));
        self.gpCourseProp()[i].addCourse(new course("3", "MATH1030", "Calculus", "City3"));
    
    if (self.gpCourseProp()[i].gpCode == "MATH1006") 
        self.gpCourseProp()[i].addCourse(new course("4", "MATH1006", "Linear algebra", "City1"));
        self.gpCourseProp()[i].addCourse(new course("6", "MATH1006", "Linear algebra", "City2"));
    
    if (self.gpCourseProp()[i].gpCode == "MATH1046") 
        self.gpCourseProp()[i].addCourse(new course("5", "MATH1046", "Discrete Math", "City1"));
        self.gpCourseProp()[i].addCourse(new course("7", "MATH1046", "Discrete Math", "City2"));
    
    


var vm = new ViewModel();
ko.applyBindings(vm);
    tr.mutated 
        display: none;
    
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table class="table">
    <thead>
        <tr>
            <th>ID</th>
            <th>Course Code</th>
            <th>Course Title</th>
            <th>Course Campus</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: gpCourseProp">
        <tr class="table-dark">
            <td></td>
            <td><span data-bind="text: $data.gpCode"></span></td>
            <td><span></span></td>
            <td></td>
        </tr>
        <!-- ko foreach: $data.courses -->
        <tr data-bind="css:  mutated: $parent.mutated.hide() == true ">
            <td><span data-bind="text: $data.id"></span></td>
            <td><span data-bind="text: $data.courseCode"></span></td>
            <td><span data-bind="text: $data.courseTitle"></span></td>
            <td><span data-bind="text: $data.coursecampus"></span></td>
        </tr>
        <!-- /ko -->
    </tbody>
</table>

我遇到的问题是尝试将课程添加到 gpCourseProperties。

【问题讨论】:

'我有 jsfiddle,但我有一些问题。这里是 jsfiddle。” 请使用 Stack Snippets([&lt;&gt;] 工具栏按钮)在这里,现场执行您的可运行示例;here's how to do one。 【参考方案1】:

主要问题是:

初始化数据时,您只需将push 的参数gpCourseProperties 传递给可观察数组。您需要使用new 构建视图模型。 当您为您的courseProperties 创建course 内容时,您检查gpCode === "Some string"。由于gpCodeobservable,因此您需要使用() 提取它的值,这样才能永远成立。

这是一个更新版本,只需进行最少的更改即可使其正常工作。 (注意,出于调试目的,我删除了隐藏某些行的 CSS)。

修复在 cmets 中标记。

function course(_id, _code, _title, _campus) 
    var self = this;
    this.id = ko.observable(_id);
    this.courseCode = ko.observable(_code);
    this.courseTitle = ko.observable(_title);
    this.coursecampus = ko.observable(_campus);


function gpCourseProperties(_code, _isHidden) 
    var self = this;
    this.gpCode = ko.observable(_code);
    this.hide = ko.observable(_isHidden);
    this.courses = ko.observableArray();

    this.addCourse = function (_id, _courseCode, _courseTitle, _courseCampus) 
        self.courses.push(new course(_id, _courseCode, _courseTitle, _courseCampus));
    

    this.switchMutated = function (code) 
        self.hide(!self.hide());
    ;
    this.switchText = ko.computed(function () 
        if (self.hide() == true) 
            return '+'
        
        return '-';
    , this);


function ViewModel() 
    var self = this;
    this.gpCourseProp = ko.observableArray();

    // Fix 1:
    //                     vvvvvvvvvvvvvvvvvvvvvvv                v
    self.gpCourseProp.push(new gpCourseProperties("MATH1030", true));
    self.gpCourseProp.push(new gpCourseProperties("MATH1006", true));
    self.gpCourseProp.push(new gpCourseProperties("MATH1046", true));

    for (i = 0; i < self.gpCourseProp().length; i++) 
        // Fix 2:
        //                               vv
        if (self.gpCourseProp()[i].gpCode() == "MATH1030") 
            self.gpCourseProp()[i].addCourse("1", "MATH1030", "Calculus", "City1");
            self.gpCourseProp()[i].addCourse("2", "MATH1030", "Calculus", "City2");
            self.gpCourseProp()[i].addCourse("3", "MATH1030", "Calculus", "City3");
        
        if (self.gpCourseProp()[i].gpCode() == "MATH1006") 
            self.gpCourseProp()[i].addCourse("4", "MATH1006", "Linear algebra", "City1");
            self.gpCourseProp()[i].addCourse("6", "MATH1006", "Linear algebra", "City2");
        
        if (self.gpCourseProp()[i].gpCode() == "MATH1046") 
            self.gpCourseProp()[i].addCourse("5", "MATH1046", "Discrete Math", "City1");
            self.gpCourseProp()[i].addCourse("7", "MATH1046", "Discrete Math", "City2");
        
    


var vm = new ViewModel();
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table class="table">
    <thead>
        <tr>
            <th>ID</th>
            <th>Course Code</th>
            <th>Course Title</th>
            <th>Course Campus</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: gpCourseProp">
        <tr class="table-dark">
            <td></td>
            <td><span data-bind="text: gpCode"></span></td>
            <td><span></span></td>
            <td></td>
        </tr>
        <!-- ko foreach: courses -->
        <tr data-bind="css:  mutated: $parent.hide() == true ">
            <td><span data-bind="text: id"></span></td>
            <td><span data-bind="text: courseCode"></span></td>
            <td><span data-bind="text: courseTitle"></span></td>
            <td><span data-bind="text: coursecampus"></span></td>
        </tr>
        <!-- /ko -->
    </tbody>
</table>

【讨论】:

以上是关于如何在 Knockout.js 中嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章

knockout.js 数据中的嵌套 foreach 显示但未正确显示

Knockout js绑定可空对象的属性

knockout.js remove 不适用于主视图模型中的嵌套视图模型和视图模型

如何使用 Knockout.js 将多个 View 绑定到单个 ViewModel

GroupBy,在 knockout.js 中过滤

在 knockout.js 中进行 ajax 检索后使字段可观察