VueJS:如何使用Google places API与多个参考文献?

问题描述 投票:0回答:1

我在工作中使用Google places API,一切都很正常。然而,我有一个独特的情况下,我需要有一个以上的送货地址,因此,我需要使谷歌地方API的工作方式。

这是我目前的代码。

<template>
  <div>
    <div v-for="(search, index) in searchInput" :key="index">
      <input type="text" ref="search" v-model="search.city">
    </div>
    <button type="button" @click="addMore">Add more</button>
  </div>
</template>

<script>
export default {
  name: "App",
  data: () => ({
    location: null,
    searchInput: [
      {
        city: ""
      }
    ]
  }),
  mounted() {
    window.checkAndAttachMapScript(this.initLocationSearch);
  },
  methods: {
    initLocationSearch() {
      let autocomplete = new window.google.maps.places.Autocomplete(
        this.$refs.search
      );
      autocomplete.addListener("place_changed", function() {
        let place = autocomplete.getPlace();
        if (place && place.address_components) {
          console.log(place.address_components);
        }
      });
    },
    addMore() {
      this.searchInput.push({ city: "" });
    }
  }
};
</script>

我从API中得到这个错误。InvalidValueError: not an instance of HTMLInputElement and b.ownerDocument is undefined

我怎么做 refs 我添加的单个项目的唯一性,然后将其传递给 initLocationSearch 方法?请大家帮忙,谢谢。

她是一个 代码和盒子 演示

javascript google-maps vue.js google-places-api googleplacesautocomplete
1个回答
2
投票

鉴于你提供的完整场景的细节,我将如何做。

我会使用一个简单的计数器来跟踪输入的数量,并设置其初始值为 1 并用它来显示输入。

<div v-for="(n, index) in this.counter" :key="index">
  <input type="text" ref="search">
</div>

然后根据计数器,将自动完成小组件绑定到最后添加的输入。

autocomplete = new window.google.maps.places.Autocomplete(
  this.$refs.search[this.counter - 1]
);

然后使用你的 addMore() 方法来递增计数器。

addMore() {
  this.counter++;
}

使用 updated() 用于每当一个新的输入被添加到DOM中时,就会触发 initLocationSearch() 方法。

updated() {
  this.initLocationSearch();
},

place_changed 事件,根据不同的输入值更新所选城市的列表。

this.selectedCities = this.$refs["search"].map(item => {
  return { city: item.value };
});

这样,无论输入值发生了什么变化,你总是有一个最新的城市列表。当然,你需要处理清空输入和可能的其他边缘情况。

完整的代码。

<template>
  <div>
    <div v-for="(n, index) in this.counter" :key="index">
      <input type="text" ref="search">
    </div>
    <button type="button" @click="addMore">Add more</button>
    <hr>Selected cities:
    <ul>
      <li v-for="(item, index) in this.selectedCities" :key="index">{{ item.city }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "App",
  data: () => ({
    selectedCities: [],
    counter: 1
  }),
  mounted() {
    window.checkAndAttachMapScript(this.initLocationSearch);
  },
  updated() {
    this.initLocationSearch();
  },
  methods: {
    setSelectedCities() {
      this.selectedCities = this.$refs["search"].map(item => {
        return { city: item.value };
      });
    },
    initLocationSearch() {
      let self = this,
        autocomplete = new window.google.maps.places.Autocomplete(
          this.$refs.search[this.counter - 1],
          {
            fields: ["address_components"] // Reduce API costs by specifying fields
          }
        );

      autocomplete.addListener("place_changed", function() {
        let place = autocomplete.getPlace();
        if (place && place.address_components) {
          console.log(place);
          self.setSelectedCities();
        }
      });
    },
    addMore() {
      this.counter++;
    }
  }
};
</script>

CodeSandbox演示


0
投票

你可以动态地绑定到 ref.D。类似于 :ref="'search' + index"

<template>
  <div>
    <div v-for="(search, index) in searchInput" :key="index">
      <input type="text" :ref="'search' + index" v-model="search.city">
    </div>
    <button type="button" @click="addMore">Add more</button>
  </div>
</template>

然后在addMore中,在创建推送一个新的对象到searchInput之前,抓住searchInput中最后一个索引。然后你可以得到新创建的 ref,并将其传递给 initLocationSearch.

    initLocationSearch(inputRef) {
      let autocomplete = new window.google.maps.places.Autocomplete(
        inputRef
      );
      autocomplete.addListener("place_changed", function() {
        let place = autocomplete.getPlace();
        if (place && place.address_components) {
          console.log(place.address_components);
        }
      });
    },
    addMore() {
      const lastInputRef = this.$refs['search' + this.searchInput.length - 1];
      this.initLocationSearch(lastInputRef);
      this.searchInput.push({ city: "" });
    }
© www.soinside.com 2019 - 2024. All rights reserved.