【问题标题】:Knockout nested model properties挖空嵌套模型属性
【发布时间】:2017-09-04 01:31:26
【问题描述】:

我需要一个像我的网络表单中的重复表这样的功能,并且需要以 JSON 格式存储我的数据,如下所示:

[
  {
    "id": 1, "name": "T01", "title": "T01 form title", "totalPoints": "total of all points for sections below",
    "sections":
        [
            { "section": "First section", "point": 4 },
            { "section": "Second section", "point": 5 }
        ]
  },
  {
    "id": 2, "name": "T02", "title": "T02 form title", "totalPoints": "total of all points for sections below",
    "sections":
        [
            { "section": "First section", "point": 4 },
            { "section": "Second section", "point": 5 }
        ]
  }

]

我正在使用淘汰赛,我在下面实现了顶层结构,但在嵌套部分中遇到了困难。

这是我构建模型的尝试,请告知使用什么选项,或者如果这不正确,请告知正确的选项:

function Form(data)
    {
        this.Id = ko.observable(data.Id);
        this.Name = ko.observable(data.Name);
        this.Title = ko.observable(data.Title);
        this.Total = ko.observable(data.Total);

    // Option 1, like an array
    this.Sections = ko.observableArray([
        {
             Section: data.Section,
             Point: data.Total
        }
    ]);

    // Option 2, like a function
    function Sections(data) {
        this.Section = ko.observable(data.Section),
        this.Point = ko.observable(data.Point)
    }
}

稍后我将这些数据作为模型推送到像这样的可观察数组,我可以再次推送顶层,但不能嵌套属性:

    self.addForm = function () {
        self.forms.push(
            new Form({
                    Id: this.id(),
                    Name: this.name(),
                    Title: this.title(),
                    Total: function() // TODO
                    // Sections nested properties implementation
                })
            );
        self.name("");
    };

【问题讨论】:

    标签: json knockout.js


    【解决方案1】:

    我会说最好定义两个视图模型:

    1. Form,和
    2. Section

    您的Form 将具有三种属性:

    1. 常规ko.observable 值,用于IdNameTitle

      注意:如果其中一些是静态的,最好不要让它们可观察。我可以想象Id 永远不会改变:您可以通过将其设置为常规字符串来向代码的其他读者发出信号。

    2. observableArray 用于您的 Sections 列表

    3. pureComputed 代表 Total,它总结了您的所有 Section 积分

    function Section(points, title) {
      // TODO: check if you need these to be observable
      this.points = points;
      this.title = title;
    };
    
    // Create a new Section from a plain object
    Section.fromData = function(data) {
      return new Section(data.point, data.section);
    };
    
    function Form(id, name, title, sections) {
      this.id = ko.observable(id);
      this.name = ko.observable(name);
      this.title = ko.observable(title);
    
      // Map using our static constructor helper
      this.sections = ko.observableArray(
        sections.map(Section.fromData)
      );
    
      this.total = ko.pureComputed(function() {
        return this.sections().reduce(function(sum, section) {
          return sum + section.points;
        }, 0);
      }, this);
    }
    
    // A helper to get from your data object to a new VM
    Form.fromData = function(data) {
      return new Form(data.id, data.name, data.title, data.sections);
    }
    
    // Apply bindings
    ko.applyBindings({
      forms: getTestData().map(Form.fromData)
    });
    
    
    // Your test data
    function getTestData() {
      return [{
          "id": 1,
          "name": "T01",
          "title": "T01 form title",
          "totalPoints": "total of all points for sections below",
          "sections": [{
              "section": "First section",
              "point": 4
            },
            {
              "section": "Second section",
              "point": 5
            }
          ]
        },
        {
          "id": 2,
          "name": "T02",
          "title": "T02 form title",
          "totalPoints": "total of all points for sections below",
          "sections": [{
              "section": "First section",
              "point": 4
            },
            {
              "section": "Second section",
              "point": 5
            }
          ]
        }
      ]
    };
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    
    <ul data-bind="foreach: forms">
      <li>
        <p data-bind="text: title"></p>
        <ul data-bind="foreach: sections">
          <li>
            <span data-bind="text: title"></span> (
            <span data-bind="text: points"></span>)
          </li>
        </ul>
        <span data-bind="text: 'total: (' + total()"></span>)
      </li>
    </ul>

    Section 类有点简单;如果您没有其他要求,您可以选择使用普通对象。

    【讨论】:

    • 您好,谢谢您的回复。如果我需要在 UI 中管理部分点,您能否告知我该怎么做?
    • 你把它设为ko.observable。在 total 计算中,您使用 section.points() 来获取值。在您的 UI 中,您可以使用 data-bind="value: points" 绑定到点
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    相关资源
    最近更新 更多