Observable的设置值未在视图中更新

时间:2016-10-02 03:55:24

标签: javascript google-maps-api-3 knockout.js

我有一堆Point对象(谷歌地图上的标记),我设置了一个点击事件监听器,它将全局变量“currentPlace”设置为等于被点击的Point对象然后我将currentPlace包装在一个可观察的希望中视图将更改,例如将显示该Point对象的信息的侧边菜单。

"use strict";
var currentPlace;
...

function initMap() {
map = new google.maps.Map(mapDiv, {
    zoom: 12,
    center: center,
    disableDefaultUI: true,
    draggable: true,
    google.maps.event.addListenerOnce(map, "idle", function() {
      var viewModel = new ViewModel(collection);
        ko.applyBindings(viewModel);
    });
}

var Point = function(place) {
    var self = this;
    self.name = place.name;
    self.pos = place.pos;
    self.type = place.type;
    self.description = place.description;
    self.clicked = map.getZoom();
    /**
        Create a marker for this destination.
  */
    self.marker = new google.maps.Marker({
        map: map,
        position: place.pos,
        title: place.name,
        icon: image,
        optimized: false,
        animation: google.maps.Animation.DROP
    });

    self.isVisible = ko.observable(false);
    /**
        Toggle for the visibility of each marker on map.
  */
  self.isVisible.subscribe(function(currentState) {
    if (currentState) {
      self.marker.setMap(map);
    } else {
      self.marker.setMap(null);
    }
  });

  self.isVisible(true);

  /**
        To re position the target marker and the map view to compensate for the shifted map view panel when the search menu pushes in from the left when the location is being clicked on the menu.
  */
    self.focusSearch = function() {
        map.setZoom(16);
        map.setCenter(self.marker.position);
        map.panBy(200,0);
        self.open();
    }
    /**
        To re position the target marker and the map view to compensate for the shifted map view panel when the menu slides in from the left when the location is being clicked on the menu.
  */
    self.focus = function() {
        map.setZoom(16);
        map.setCenter(self.marker.position);
        map.panBy(-200, 0);
        self.open();
    }
    /**
        Display the name and a brief description of the location in a infowindow for the corresponding marker. Also checks if the map view, in this case the zoom level has changed, if so then change the map view and re center it to the marker of the loaction that is selected. Applies to only when the regular menu is active.
    */
    self.open = function() {
        var contentString = "<h2>" + place.name + "</h2><br>";
        infowindow.setContent(contentString + place.description);
        infowindow.open(map, self.marker);
    }
    /**
        Dismiss the infowindow.
    */
    self.close = function() {
        infowindow.close();
        self.marker.setAnimation(null);
    }
    /**
        Additional event listeners for the marker.
    */
    self.marker.addListener("mouseover", function() {
        self.open();
        self.marker.setAnimation(google.maps.Animation.BOUNCE);
    });

    self.marker.addListener("mouseout", function() {
        self.marker.setAnimation(null);
    });

    self.marker.addListener("click", function() {
        currentPlace = self;
        map.setZoom(16);
        map.setCenter(self.marker.position);
        pushLeft.close();
        slideLeft.close();
        slideBottom.open();
        self.open();
    });
}
/**
        This is our ViewModel that handles displaying a menu of destinations, filter/search through the menu and finally displaying markers of these destinations on the map.
*/
var ViewModel = function(list) {
    var self = this;
    /**
     * Create a Place object for each object in the initial array and
     * place them in a new observable array.
    */
    self.allPlaces = ko.observableArray(list.map(function(place) {
        return new Point(place);
    }));

    self.search = ko.observable("");
    currentPlace = self.allPlaces()[0];
    self.selected = ko.observable();


    /**
     * Filter locations out of the menu view for any unmatched results.
     * Filter by name, description and type.
    */
    self.searchResult = ko.pureComputed(function() {
        var q = self.search().toLowerCase();
        return self.allPlaces().filter(function(place) {
            return ((place.name.toLowerCase().indexOf(q) >= 0) || (place.description.toLowerCase().indexOf(q) >= 0) || (place.type.toLowerCase().indexOf(q) >= 0));
        });
    });
    /**
     * Filter markers out of the map view for any unmatched results.
     * Filter by name, description and type.
    */
    self.filterMarkers = ko.computed(function () {
    var q  = self.search().toLowerCase();
    return ko.utils.arrayFilter(self.allPlaces(), function (place) {
        var doesMatch = ((place.name.toLowerCase().indexOf(q) >= 0) || (place.description.toLowerCase().indexOf(q) >= 0) || (place.type.toLowerCase().indexOf(q) >= 0));
        place.isVisible(doesMatch);
        return doesMatch;
    });
  });
}

1 个答案:

答案 0 :(得分:0)

Knockout无法正常工作。将GUI与视图模型联系起来的唯一方法是直接使用observable。

在您的情况下,最好的做法是将全局currentPlace变量作为可观察对象移动到视图模型中。要在以后访问它,请创建视图模型的全局实例。

var vm = new ViewModel();

// Later on, access currentPlace this way:
vm.currentPlace();