Vue3组合式API中如何在Google Maps InfoWindow内使用Vuetify组件
在Vue3组合式API中为Google Maps Marker的InfoWindow集成Vuetify组件
你当前的问题核心在于三点:
- 直接传递HTML字符串用
{{ content }}渲染会被Vue自动转义,导致显示纯文本 createApp创建的独立应用未继承主应用的Vuetify上下文,Vuetify组件无法被正确解析- 错误地将HTML字符串作为内容传递,而非直接在组件中使用Vuetify组件
以下是可行的实现方案:
1. 重构InfoWindow子组件
直接在组件内使用Vuetify组件,通过props传递数据和事件,避免HTML字符串传递:
<script setup lang="ts"> defineProps<{ btnText: string; onBtnClick: () => void; }>(); </script> <template> <v-card width="200"> <v-card-text> <v-btn @click="onBtnClick" color="primary"> {{ btnText }} </v-btn> </v-card-text> </v-card> </template>
2. 修改主组件代码
复用主应用的Vuetify上下文渲染组件,同时处理InfoWindow关闭后的组件销毁,避免内存泄漏:
<script setup lang="ts"> import { onMounted, ref, createVNode, render } from "vue"; import { useVuetify } from "vuetify"; import infowindowVue from "./infowindow.vue"; const position = { lat: 63.42805, lng: 10.41033 }; let googleMap = ref<google.maps.Map>(); const vuetify = useVuetify(); // 获取主应用的Vuetify实例 onMounted(async () => { const { Map } = (await google.maps.importLibrary( "maps" )) as google.maps.MapsLibrary; googleMap.value = new Map( document.getElementById("googleMap") as HTMLElement, { center: position, zoom: 4, } ); const map = googleMap.value; const marker = new google.maps.Marker({ position, map, animation: google.maps.Animation.DROP, title: "punto de interés", }); const infoWindowWrapper = document.createElement("div"); let infoWindowInstance: google.maps.InfoWindow | null = null; // 定义组件的props const componentProps = { btnText: "hola", onBtnClick: () => { console.log("按钮被点击"); infoWindowInstance?.close(); }, }; // 创建组件VNode并传入Vuetify上下文 const vNode = createVNode(infowindowVue, componentProps, null, { vuetify, }); marker.addListener("click", () => { // 渲染组件到容器 render(vNode, infoWindowWrapper); // 创建并打开InfoWindow infoWindowInstance = new google.maps.InfoWindow({ content: infoWindowWrapper, ariaLabel: "Trondheim", }); infoWindowInstance.open({ anchor: marker, map, }); // 监听关闭事件,销毁组件释放资源 infoWindowInstance.addListener("closeclick", () => { render(null, infoWindowWrapper); infoWindowInstance = null; }); }); }); </script> <template> <v-container fluid> <v-row justify="center"> <v-col cols="12" class="pa-0"> <div id="googleMap" ref="googleMap"></div> </v-col> </v-row> </v-container> </template> <style scoped> #googleMap { height: 500px; width: 100%; } </style>
关键说明
- 复用Vuetify上下文:通过
useVuetify()获取主应用的Vuetify实例,传递给VNode上下文,确保Vuetify组件能正常渲染 - 避免HTML转义:直接在子组件中编写Vuetify代码,通过props传递动态数据和事件
- 内存泄漏处理:监听InfoWindow的
closeclick事件,调用render(null, wrapper)销毁组件 - 使用createVNode:替代
createApp,在主应用上下文内渲染组件,继承所有已注册的插件和样式
内容的提问来源于stack exchange,提问作者tsiPlus
相关产品推荐
相关产品推荐

