簡體   English   中英

淘汰賽:observableArray可觀察輸入數組

[英]Knockout: observableArray of arrays of observable inputs

我在項目Flight Management Computer中遇到了route.htmlforeach綁定問題。


問題1: observableArray value綁定全部同時更新

對於javascript中的路由,我設置了一個ko.observableArray Arrayko.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-bind作為text: $data[x]而不是value 該不同的文件可以正常工作,沒有任何問題。 不同的文件是log.html


問題2(或更確切地說,一個問題)

解決route問題后,當同一數組中的另一個值發生更改時,我希望更新單個數組(一個航點輸入字段)中的某些特定值。 IE瀏覽器

// 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是整個項目的最重要特征。

問題1:這是一個與javascript相關的問題,而不是淘汰賽。 您一次又一次地推送對同一對象的引用,從而使您的observableArray包含對同一對象的多個引用。 您應該更改代碼,改為使用工廠函數:

var DEFAULT_ROUTE = function(){
  return [
    ko.observable(), // Waypoint Name
    ko.observable(), // Lat.
    ko.observable(), // Lon.
    ko.observable(), // Altitude Restriction
    ko.observable(false), // Waypoint isValid
    ko.observable('') // Waypoint information
  ];
};

然后推:

route.push(DEFAULT_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的正確基礎:

由於您現在有了一個定義明確的模型,因此可以開始使用subscribecomputed定義屬性之間的關系。 您想要更改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);
};

現在,您有了一個具有isValid: falselat: nulllon:null的默認Route ,並且當將waypointName設置為字符串值時,例如route.waypointName("WAATR") ,所有屬性都會自動更新。

嗨, user3297291 ,謝謝您的幫助! 根據您的建議,我能夠完成此功能:

var Route = function () {

    var self = this;

    // Waypoint name
    var _fix = ko.observable();
    self.fix = ko.pureComputed({
        read: function () {
            return _fix();
        },
        write: function (val) {
            _fix(val);

            var coords = get.waypoint(val);
            var isValid = coords[0] && coords[1];

            self.lat(coords[0], isValid);
            self.lon(coords[1], isValid);
            self.info(coords[2]);
        }
    });

    // Latitude
    var _lat = ko.observable();
    self.lat = ko.pureComputed({
        read: function () {
            return _lat();
        },
        write: function (val, isValid) {
            _lat(val);
            self.valid(isValid ? true : false);
        }
    });

    // longitude
    var _lon = ko.observable();
    self.lon = ko.pureComputed({
        read: function () {
            return _lon();
        },
        write: function (val, isValid) {
            _lon(val);
            self.valid(isValid ? true : false);
        }
    });

    // Is waypoint valid
    self.valid = ko.observable(false);

    // Waypoint info
    self.info = ko.observable();

};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM