javascript - knockout : observableArray of arrays of observable inputs

标签 javascript knockout.js foreach

I am having problems with route.html's foreach binding in the project Flight Management Computer.

<小时/>

问题1:value绑定(bind)于 observableArray所有同时更新

对于javascript中的路由,我设置了ko.observableArrayArrayko.observable (听起来很令人困惑,但下面仍然附有代码):

/* All bindings applied to viewmodel already */

var route = ko.observableArray();
var DEFAULT_ROUTE = [
    ko.observable(), // Waypoint Name
    ko.observable(), // Lat.
    ko.observable(), // Lon.
    ko.observable(), // Altitude Restriction
    ko.observable(false), // Waypoint isValid
    ko.observable('') // Waypoint information
];

单击特定按钮会添加 DEFAULT_ROUTE没有问题,正如它所说的

route.push(DEFAULT_ROUTE);

HTML 代码大致如下所示,并且没有 UI 问题:

<tbody data-bind="foreach: route">
    <tr class="wpt-row">
        <td><input data-bind="value: $data[0]"></td> <!--waypoint input-->
        <td><input data-bind="value: $data[1]"></td> <!--lat. input-->
        <td><input data-bind="value: $data[2]"></td> <!--lon. input-->
        <td><input data-bind="value: $data[3]"></td> <!--alt. input-->
    </tr>
</tbody>

但是,当外部ko.observableArray中有多个数组时,就会出现问题。 ,因为在 UI 和 JavaScript 中更改一个输入值都会更新每个数组中的所有值。示例:

var route = ko.observableArray([DEFAULT_ROUTE, DEFAULT_ROUTE, DEFAULT_ROUTE]);

// Then, outside viewmodel (in javascript console)
route()[0][0]('WPT'); // Sets the waypoint of the first input field to be 'WPT'

// Later
route()[0][0](); // 'WPT', correct
route()[1][0](); // 'WPT', incorrect, should be undefined
route()[2][0](); // 'WPT', incorrect, should be undefined

我设置了类似的foreach在不同的文件中,但带有 <input>就像 <span> ,和data-bindtext: $data[x]而不是value 。那个不同的文件工作正常,没有任何问题。不同的文件是 log.html

<小时/>

问题 2(或者更确切地说,一个问题)

route之后问题已解决,我希望当同一数组中的另一个值发生更改时更新单个数组(一个航路点输入字段)中的某些特定值。即:

// Scenario 1, waypoint is a valid waypoint with proper coords
var waypoint = 'WAATR';
var coords = getWaypoint(waypoint); // [42.1234, -70.9876]
route()[0][0](waypoint); 
// route()[0][0]() is now 'WAATR'
// route()[0][1] and route()[0][2] should automatically update with value `coords[0]` and `coords[1]`
// route()[0][4] should be set to true (valid waypoint)


// Scenario 2, waypoint is NOT a valid waypoint
var waypoint = 'IDK';
var coords = getWaypoint(waypoint); // []
route()[0][0](waypoint);
// route()[0][0]() is now 'IDK'
// route()[0][1] and route()[0][2] should remain undefined, waiting for users to manually input coordinates
// route()[0][4] should be false (invalid waypoint)

我阅读了文档,其中有一个 extend功能,但我不太明白。现在的挑战是如何将这些自动填充功能限制为特定数组(航点输入字段),而不是(如问题#1)整个输入数据表。

如果有人能提供帮助,我将不胜感激,因为 route是整个项目最重要的特点。

最佳答案

您确实应该使用对象而不是数组。它使一切变得更容易阅读和理解,并且极大地帮助调试。

var Route = function() {
  this.waypointName = ko.observable();

  this.lat = ko.observable();
  this.lon = ko.observable();

  this.altitudeRestriction = ko.observable();
  this.isValid = ko.observable(false);
  this.waypointInfo = ko.observable('');
};

就像您已经想到的那样,您现在可以通过调用 new Route() 来使用它。您将解决问题 1 并拥有更易于阅读和维护的代码。解决问题 2 的正确基础:

因为您现在有了一个明确定义的模型,所以您可以开始使用 subscribecompulated 定义属性之间的关系。您想要更改 waypointName 属性并让其他属性自动更新:

var Route = function() {
  this.waypointName = ko.observable();

  // Automatically updates when you set a new waypoint name
  var coords = ko.pureComputed(function() {
    return getWaypoint(this.waypointName());
  }, this);

  // Check if we got correct coords
  this.isValid = ko.pureComputed(function() {
    return coords().length === 2;
  }, this);

  // Auto-extract lat from coords, null if invalid
  this.lat = ko.pureComputed(function() {
    return this.isValid() 
      ? coords()[0]
      : null;
  }, this);

  // Auto-extract lat from coords, null if invalid
  this.lon = ko.pureComputed(function() {
    return this.isValid() 
      ? coords()[1]
      : null;
  }, this);
};

您现在拥有一条默认Route,其中包含isValid: falselat: nulllon:null 和当您将 waypointName 设置为字符串值(例如 route.waypointName("WAATR"))时,所有属性都会自动更新。

关于javascript - knockout : observableArray of arrays of observable inputs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45272302/

相关文章:

javascript - 如何使单击事件适用于具有相同类的多个元素?

javascript - 如何修复出现在 materializecss 自动完成中的这个空白列表?(Internet Explorer)

javascript - 在外部函数中 knockout 可观察数组索引

javascript - Knockout.js 预种子 ObservableArray

javascript - 为什么原生 javascript 数组 forEach 方法明显慢于标准 for 循环?

c++ - 使用 foreach 循环修改 Qt 数据结构的正确方法

javascript - 从 chrome.webRequest.onBeforeSendHeaders 中提取 cookie

javascript - 在 React Native 的 Webview 中嵌入 youtube 视频

knockout.js - 来自 ko.toJSON 的访问被拒绝

java - Java foreach 对原语的迭代顺序是否精确定义?