ko.mapping(更新数组问题)

时间:2016-12-09 10:44:17

标签: javascript knockout.js

我遇到了ko.mapping的问题 1)在客户端ViewModel上:

var data = [ {id : 1, title: "C"} ]

2)从服务器(对象数组):

[ {id : 1, title: "C"},{number : 2, title: "B" } ]

3)我只有在存在时才需要替换数据:

[ {id : 1, title: "C"} ] => data replace self.books

3)我尝试使用ko.mapping插件,但结果为var mappingOptions = { key: function (data) { return ko.utils.unwrapObservable(data.id); } }; ko.mapping.fromJS(data, mappingOptions, self.books);

awk -F '=| ' '/^ts=/{printf $2","} /de ad be ef/{if(!a){printf $15$16;a=1}else{print $1$2;a=0}}' data.log

THX:)

1 个答案:

答案 0 :(得分:1)

你可以(可能)使用ko.mapping插件,但我认为如果你试图在普通的javascript中解决这个问题,它会让你受益。代码不多,至少你会更好地理解插件在幕后做的事情。

您的books数组需要与更新数组(data)合并。您使用id属性来检查是否相等。因此,简而言之,您必须:

  • 循环更新
  • 找到与id匹配的旧书
  • 将其替换为新书
  • 使用更新后的列表设置books数组,以便淘汰赛可以找出已更改的内容

直接实现更新功能:



var books = ko.observableArray([ 
  {id : 1, title: "A"},
  {id : 2, title: "B" } 
]);

var updateBooks = function(updates) {
  var oldBooks = books();
  var newBooks = oldBooks.map(function(book) {
    var update = updates.find(function(update) {
      return update.id === book.id;
    });
    
    return update || book;
  });
  books(newBooks);  
};

ko.applyBindings({
  books: books,
  updateBooks: updateBooks
});

updateBooks([{ id: 1, title: "C" }]);

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<ul data-bind="foreach: books">
  <li>
    <span data-bind="text:id"></span>
    <strong data-bind="text: title"></strong>
</ul>
&#13;
&#13;
&#13;

如果您不介意性能要求,并且您可以确定更新中的所有id已在oldBooks中提供(即更新),则此实施将有效不包含书籍。它还创建了一个包含新旧书对象组合的新数组。这使得淘汰赛更难以有效地呈现列表。

通过更多工作,您可以制作具有可观察title属性的书籍视图模型。通过使用基于id的地图,您可以加快更新周期。

&#13;
&#13;
var Book = function(options) {
  this.id = options.id;
  this.title = ko.observable(options.title);
  
  // Instead of creating new Books all the time,
  // we update its observable property so only the changed values
  // are re-rendered
  this.update = function(options) {
    this.title(options.title);
  }.bind(this);
};

Book.create = function(options) { return new Book(options); };

var BookList = function(bookData) {
  this.books = ko.observableArray(bookData.map(Book.create));

  // Compute an object that stores each book by id.
  // Whenever the books array changes, this object is updated.
  // Access a book by calling: this.bookMap()[bookId]
  this.bookMap = ko.pureComputed(function() {
    return this.books().reduce(function(map, book) {
      map[book.id] = book;
      return map;
    }, {});
  }, this);
};

BookList.prototype.updateBooks = function(updates) {
  // Apply each update
  updates.forEach(function(newBook) {
    // Find the book by id in our map
    var bookRef = this.bookMap()[newBook.id];
    if (bookRef) {
      // The book has its own viewmodel, with an update method
      bookRef.update(newBook);
    }
  }.bind(this));
};

var data = [ 
  {id : 1, title: "A"},
  {id : 2, title: "B" } 
];

var vm = new BookList(data);
ko.applyBindings(vm);

vm.updateBooks([{ id: 1, title: "C" }]);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<ul data-bind="foreach: books">
  <li>
    <span data-bind="text:id"></span>
    <strong data-bind="text: title"></strong>
</ul>
&#13;
&#13;
&#13;