在knockoutjs中订阅observableArray的最简单方法

时间:2013-05-10 12:29:25

标签: google-maps knockout.js observable subscribe

我有一个带有一些标记的observableArray,例如:

var markers = ko.observableArray([
  { 
    id: 0, 
    title: ko.observable("Marker 0"), 
    lat: ko.observable(55.31),
    lng: ko.observable(11)
  },
  {
    id: 1, 
    title: ko.observable("Marker 1"), 
    lat: ko.observable(57.20),
    lng: ko.observable(15.5)
  }
]);

此数组被发送到某个MapWidget对象,该对象必须为每个元素创建谷歌地图标记。它必须在以下情况下移动标记lat,lng observables更改,在标题可观察更改的情况下更改标记的标题等等。

这意味着在MapWidget中有一些googlemap标记数组,它应该与给定的observableArray连接。连接它们的最佳和最简单的方法是什么?

UPD。有关MapWidget的更多细节。

MapWidget是一个可以访问某些谷歌地图地图对象的对象,它接收一个带有上述标记的observableArray作为参数。

var MapWidget = function(markers) {
  var div = $("#map").get(0);
  this.map = new gmaps.Map(div);
  /* 
    The magic goes here:
    markers is an observableArray, we subscribe for it's changes, 
    create gmaps.marker for each new element, 
    destroy in case of destroying them from array, 
    move and rename each marker in case of corresponding changes
  */
}  

1 个答案:

答案 0 :(得分:2)

您可以订阅这样的数组:

ar.subscribe(function() {
  // clean and redraw all markers
});

如果您这样做,您将在向阵列添加/从阵列中删除项目时收到通知。但不是在修改项目的属性时。

如果您想根据项目中的各个属性更改更新Google地图标记,则可以实施simple dirty flag mechanism,然后单独订阅每个项目。由于每个项目都有一个id,我认为它是唯一的,你可以创建一个地图,其中键/值对是id和地图小部件。

所以,给出每个项目:

var item = function(data) {
  var self = this;
  self.isChanged = ko.observable(self);
  self.id = data.id;
  self.title = ko.observable(data.title);
  self.title.subscribe(function() { self.isChanged(self); self.isChanged.valueHasMutated(); });
  self.lat = ko.observable(data.lat);
  self.lat.subscribe(function() { self.isChanged(self); self.isChanged.valueHasMutated(); });
  self.lng = ko.observable(data.lng);
  self.lng.subscribe(function() { self.isChanged(self); self.isChanged.valueHasMutated(); });
}

给出一个假设图,你可以在标记和项目之间保持链接:

var markersMap = [];
markersMap[0] = yourGoogleMapWidget;

然后,您可以订阅跟踪以下项目的更改:

ar[0].isChanged.subscribe(function(item) {
  var myGMapMarker = markersMap[item.id()];
  // update your marker, or destroy and recreate it...
});