【问题标题】:List Place Names Using Google Places API and KnockoutJS使用 Google Places API 和 KnockoutJS 列出地名
【发布时间】:2019-01-06 06:30:30
【问题描述】:

我想检索 Google Places API 搜索返回的名称并使用 KnockoutJS 列出它们。

我想使用 Google Places API 搜索地点。我想在地图上标记这些地方,并使用 KnockoutJS 在无序列表中列出它们的名称。我能够将这些标记放在地图上,但无法使用 KnockoutJS 在无序列表中列出它们的名称。这是我的代码。

HTML:

<h4>Search Results<h4>
    <ul class="binding" data-bind="foreach: placesArray">
        <li class="binding" data-bind="text: $data">
            <span class="binding" data-bind="text: $index"></span>
        </li>
</ul>

JavaScript:

我发现极其困难的是我无法将placesArray = getNames(results) 存储在全局变量placesArray 中。我认为如果我在本地添加 knockoutJS 可能会起作用,但如果我第二次搜索,ko.applyBindings 会导致错误。

let placesArray;
function searchPlaces() {
    let bounds = map.getBounds();
    hideMarkers(placeMarkers);
    let placesService = new google.maps.places.PlacesService(map);
    let placeName = placeInput.value;
    placesService.textSearch({
        query: placeName, // placeName is a string like "restaurants"
        bounds: bounds
    }, function(results, status) {
        if (status == google.maps.places.PlacesServiceStatus.OK) {
            createMarkers(results);
            placesArray = getNames(results);
            // placesArray is an array of strings like ["McDonalds", "KFC", "Wendy's",...], I want to list them in <li> //
        }
    });
}

function getNames(placesArray) {
    let placeNamesArray = [];
    for (let i=0; i < placesArray.length; i++) {
        let name = placesArray[i].name;
        placeNamesArray.push(name);
    }
    return placeNamesArray;
}

如果我在本地引入了 KnockoutJS,则名称会正确列出,但如果我第二次运行此函数,则仅列出一次。 ko.applyBindings 会抛出错误,因为我多次将绑定应用于相同的元素。

function searchPlaces() {
    let bounds = map.getBounds();
    hideMarkers(placeMarkers);
    let placesService = new google.maps.places.PlacesService(map);
    let placeName = placeInput.value;
    placesService.textSearch({
        query: placeName,
        bounds: bounds
    }, function(results, status) {
        if (status == google.maps.places.PlacesServiceStatus.OK) {
            createMarkers(results);
            let placesArray = getNames(results);
            let SimpleListModel = function() {
                this.placesArray = ko.observableArray(placesArray);
            }
            ko.applyBindings(new SimpleListModel());
        }
    });
}

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

    viewmodel 和 Knockout observable 的想法是,您可以在获得任何新信息时对其进行更新,并将其反映在 HTML 中。因此,您最初可以创建一个空的 observable,然后用您搜索的值填充它。

    let SimpleListModel = function() {
        this.placesArray = ko.observableArray();
    }
    let modelInstance = new SimpleListModel();
    ko.applyBindings(modelInstance);
    
    function searchPlaces() {
        let bounds = map.getBounds();
        hideMarkers(placeMarkers);
        let placesService = new google.maps.places.PlacesService(map);
        let placeName = placeInput.value;
        placesService.textSearch({
            query: placeName,
            bounds: bounds
        }, function(results, status) {
            if (status == google.maps.places.PlacesServiceStatus.OK) {
                createMarkers(results);
                let placesArray = getNames(results);
                modelInstance.placesArray(placesArray);
            }
        });
    }
    

    【讨论】:

      【解决方案2】:

      您需要创建一个带有属性和方法的视图模型,并且它应该只被实例化一次。像这样的:

      function ViewModel() {
          var vm = this;
      
          vm.placesArray = ko.observableArray();
      
          vm.getNames = function () {
              let placeNamesArray = [];
              for (let i=0; i < placesArray.length; i++) {
                  let name = placesArray[i].name;
                  placeNamesArray.push(name);
              }
              return placeNamesArray;
          };
      
          vm.getPlaces = function () {
              let bounds = map.getBounds();
              let placesService = new google.maps.places.PlacesService(map);
              let placeName = placeInput.value;
      
              hideMarkers(placeMarkers);
      
              placesService.textSearch({
                  query: placeName,
                  bounds: bounds
              }, function(results, status) {
                  if (status == google.maps.places.PlacesServiceStatus.OK) {
                      createMarkers(results);
                      vm.placesArray(vm.getNames(results));
                  }
              }); 
          };
      }
      
      ko.applyBindings(new ViewModel());
      

      注意这里还有很多未定义的变量(例如,您没有提供 createMarkershideMarkers 函数,mapplaceMarkers 也将是未定义的),所以这段代码不会工作,但这应该是它的要点。

      您可能还应该在您的视图模型上设置placeInput 属性(并使用textInput 绑定将输入字段绑定到它),并且您可能希望在getPlaces 函数更改时执行它,这也可以通过 Knockout 轻松完成。

      【讨论】:

      • 感谢您的回答。让我测试一下。
      • 我应该将生成地图的 initMap 函数放在 ViewModel() 内部还是外部?
      猜你喜欢
      • 1970-01-01
      • 2015-10-07
      • 2012-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多