NuxtJS (Vue.js) Google v-if 中的地图和自动完成一旦切换就不会显示,仅在初始页面加载时显示
NuxtJS (Vue.js) Google Maps & Autocomplete inside v-if won't show once toggled, only on initial page load
设置一个非常简单的内部站点的基本功能,我有一个复选框来切换 div on/off(默认打开),里面的 div 是 Google 地图和自动完成。
在初始页面加载时 Google 地图和自动完成会出现并成功运行,但是如果关闭并重新打开,页面要么是空白的,要么显示错误 Map: Expected mapDiv of type Element but was passed undefined.
行为的屏幕记录: https://i.imgur.com/DhShl1s.mp4
main.vue:
<template>
<div>
Hi {{ username }}
<input
v-model="businessName"
type="text"
placeholder="Business Name"
/><br /><br />
In-store Address:<br />
<input type="checkbox" @click="toggle()" />Not applicable<br /><br />
<div v-if="instore">
<input type="text" ref="citySearch" @changed="changed" /><br /><br />
<div style="height:800px;width:800px" ref="map"></div>
<br /><br />
</div>
<button type="button" @click="updateMap">Submit</button><br />
</div>
</template>
<script>
export default {
data() {
return {
businessName: "",
businessAddress: "",
instore: true
};
},
mounted() {
this.$maps.makeAutoComplete(this.$refs.citySearch);
this.$maps.showMap(this.$refs.map, -33.86, 151.2);
},
computed: {
username() {
return this.$store.state.username;
}
},
methods: {
toggle() {
this.instore = !this.instore;
this.$maps.makeAutoComplete(this.$refs.citySearch);
this.$maps.showMap(this.$refs.map, -33.86, 151.2);
},
submit(e) {
if (!this.businessName || !this.businessAddress) {
return;
}
this.$store.commit("add_business", this.name, this.address);
},
updateMap() {
this.$maps.showMap(this.$refs.map, this.lat, this.lng);
},
changed(event) {
console.log(event);
const place = event.detail;
this.$maps.showMap(
this.$refs.map,
place.geometry.location.lat(),
place.geometry.location.lng()
);
}
}
};
</script>
maps.client.js:
let isLoaded = false;
let waiting = [];
addScript();
inject("maps", {
showMap,
makeAutoComplete
});
function addScript() {
const script = document.createElement("script");
script.src =
"https://maps.googleapis.com/maps/api/js?key=API_KEY&libraries=places&callback=initGoogleMap";
script.async = true;
window.initGoogleMap = initGoogleMap;
document.head.appendChild(script);
}
function initGoogleMap() {
isLoaded = true;
waiting.forEach(item => {
if (typeof item.fn === "function") {
item.fn(...item.arguments);
}
});
waiting = [];
}
function makeAutoComplete(input) {
if (!isLoaded) {
waiting.push({ fn: makeAutoComplete, arguments });
return;
}
const autoComplete = new window.google.maps.places.Autocomplete(input);
autoComplete.addListener("place_changed", () => {
const place = autoComplete.getPlace();
input.dispatchEvent(new CustomEvent("changed", { detail: place }));
});
}
function showMap(canvas, lat, lng) {
if (!isLoaded) {
waiting.push({
fn: showMap,
arguments
});
return;
}
const mapOptions = {
zoom: 18,
center: new window.google.maps.LatLng(lat, lng),
disableDefaultUI: true,
zoomControl: true
};
const map = new window.google.maps.Map(canvas, mapOptions);
const position = new window.google.maps.LatLng(lat, lng);
const marker = new window.google.maps.Marker({ position });
marker.setMap(map);
return;
}
}
非常感谢任何帮助,我是 Vue.JS 的新手,谢谢。
将 v-if
更改为 v-show
解决了问题,不确定这是否是最好的方法,但目前有效。
设置一个非常简单的内部站点的基本功能,我有一个复选框来切换 div on/off(默认打开),里面的 div 是 Google 地图和自动完成。
在初始页面加载时 Google 地图和自动完成会出现并成功运行,但是如果关闭并重新打开,页面要么是空白的,要么显示错误 Map: Expected mapDiv of type Element but was passed undefined.
行为的屏幕记录: https://i.imgur.com/DhShl1s.mp4
main.vue:
<template>
<div>
Hi {{ username }}
<input
v-model="businessName"
type="text"
placeholder="Business Name"
/><br /><br />
In-store Address:<br />
<input type="checkbox" @click="toggle()" />Not applicable<br /><br />
<div v-if="instore">
<input type="text" ref="citySearch" @changed="changed" /><br /><br />
<div style="height:800px;width:800px" ref="map"></div>
<br /><br />
</div>
<button type="button" @click="updateMap">Submit</button><br />
</div>
</template>
<script>
export default {
data() {
return {
businessName: "",
businessAddress: "",
instore: true
};
},
mounted() {
this.$maps.makeAutoComplete(this.$refs.citySearch);
this.$maps.showMap(this.$refs.map, -33.86, 151.2);
},
computed: {
username() {
return this.$store.state.username;
}
},
methods: {
toggle() {
this.instore = !this.instore;
this.$maps.makeAutoComplete(this.$refs.citySearch);
this.$maps.showMap(this.$refs.map, -33.86, 151.2);
},
submit(e) {
if (!this.businessName || !this.businessAddress) {
return;
}
this.$store.commit("add_business", this.name, this.address);
},
updateMap() {
this.$maps.showMap(this.$refs.map, this.lat, this.lng);
},
changed(event) {
console.log(event);
const place = event.detail;
this.$maps.showMap(
this.$refs.map,
place.geometry.location.lat(),
place.geometry.location.lng()
);
}
}
};
</script>
maps.client.js:
let isLoaded = false;
let waiting = [];
addScript();
inject("maps", {
showMap,
makeAutoComplete
});
function addScript() {
const script = document.createElement("script");
script.src =
"https://maps.googleapis.com/maps/api/js?key=API_KEY&libraries=places&callback=initGoogleMap";
script.async = true;
window.initGoogleMap = initGoogleMap;
document.head.appendChild(script);
}
function initGoogleMap() {
isLoaded = true;
waiting.forEach(item => {
if (typeof item.fn === "function") {
item.fn(...item.arguments);
}
});
waiting = [];
}
function makeAutoComplete(input) {
if (!isLoaded) {
waiting.push({ fn: makeAutoComplete, arguments });
return;
}
const autoComplete = new window.google.maps.places.Autocomplete(input);
autoComplete.addListener("place_changed", () => {
const place = autoComplete.getPlace();
input.dispatchEvent(new CustomEvent("changed", { detail: place }));
});
}
function showMap(canvas, lat, lng) {
if (!isLoaded) {
waiting.push({
fn: showMap,
arguments
});
return;
}
const mapOptions = {
zoom: 18,
center: new window.google.maps.LatLng(lat, lng),
disableDefaultUI: true,
zoomControl: true
};
const map = new window.google.maps.Map(canvas, mapOptions);
const position = new window.google.maps.LatLng(lat, lng);
const marker = new window.google.maps.Marker({ position });
marker.setMap(map);
return;
}
}
非常感谢任何帮助,我是 Vue.JS 的新手,谢谢。
将 v-if
更改为 v-show
解决了问题,不确定这是否是最好的方法,但目前有效。