You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:22:15