Vue3 + MapLibre 地图管理工具 useMap 使用指南

Vue3 + MapLibre 地图管理工具 useMap 使用指南

这里只是hooks useMap的封装使用,没有对地图组件进行封装,地图组件封装
地图组件封装

useMap.ts

import { Map } from 'maplibre-gl';
import { markRaw } from 'vue';

/**
 * 地图实例接口
 */
interface MapInstance {
  id: string;
  map: Map;
  isDestroyed: boolean;
  createdAt: number;
}

/**
 * 等待地图的回调函数类型
 */
interface MapWaitCallback {
  resolve: (map: Map) => void;
  reject: (error: Error) => void;
  timeout?: NodeJS.Timeout;
}

/**
 * 使用闭包创建多地图实例管理器
 * 提供安全的地图实例存储、获取和销毁功能
 */
const createMapManager = (() => {
  // 私有变量:存储多个地图实例,使用markRaw避免Vue响应式处理
  const mapInstances: Record<string, MapInstance> = {};
  
  // 私有变量:当前活跃的地图ID
  let activeMapId: string | null = null;
  
  // 私有变量:地图ID计数器
  let mapIdCounter = 0;

  // 私有变量:等待地图初始化的回调队列
  const waitingCallbacks: Record<string, MapWaitCallback[]> = {};

  /**
   * 生成唯一的地图ID
   */
  const generateMapId = (): string => {
    return `map_${++mapIdCounter}_${Date.now()}`;
  };

  /**
   * 触发等待回调
   * @param mapId - 地图ID
   * @param map - 地图实例
   */
  const triggerWaitingCallbacks = (mapId: string, map: Map): void => {
    const callbacks = waitingCallbacks[mapId];
    if (callbacks && callbacks.length > 0) {
      callbacks.forEach(callback => {
        if (callback.timeout) {
          clearTimeout(callback.timeout);
        }
        callback.resolve(map);
      });
      delete waitingCallbacks[mapId];
    }
  };

  /**
   * 触发等待回调的错误
   * @param mapId - 地图ID
   * @param error - 错误信息
   */
  const triggerWaitingCallbacksError = (mapId: string, error: Error): void => {
    const callbacks = waitingCallbacks[mapId];
    if (callbacks && callbacks.length > 0) {
      callbacks.forEach(callback => {
        if (callback.timeout) {
          clearTimeout(callback.timeout);
        }
        callback.reject(error);
      });
      delete waitingCallbacks[mapId];
    }
  };

  return {
    /**
     * 添加地图实例
     * @param map - MapLibre地图实例
     * @param customId - 自定义地图ID(可选)
     * @returns 返回地图ID
     * @throws 如果传入的不是有效的Map实例则抛出错误
     */
    addMap(map: Map, customId?: string): string {
      if (!(map instanceof Map)) {
        throw new Error('Invalid map instance provided. Expected MapLibre Map instance.');
      }
      
      const mapId = customId || generateMapId();
      
      // 如果已经存在相同ID的地图实例,先销毁旧实例
      if (mapInstances[mapId]) {
        console.warn(`Replacing existing map instance with ID: ${mapId}`);
        this.destroyMap(mapId);
      }
      
      // 创建新的地图实例记录
      const mapInstance: MapInstance = {
        id: mapId,
        map: markRaw(map),
        isDestroyed: false,
        createdAt: Date.now()
      };
      
      mapInstances[mapId] = mapInstance;
      
      // 如果是第一个地图实例,设置为活跃地图
      if (!activeMapId) {
        activeMapId = mapId;
      }
      
      // 触发等待该地图的回调
      triggerWaitingCallbacks(mapId, map);
      
      // 如果有等待活跃地图的回调,也要触发
      if (mapId === activeMapId) {
        triggerWaitingCallbacks('active', map);
      }
      
      return mapId;
    },

    /**
     * 获取地图实例(同步版本)
     * @param mapId - 地图ID,如果不提供则返回活跃的地图
     * @returns 返回地图实例
     * @throws 如果地图不存在或已销毁则抛出错误
     */
    getMap(mapId?: string): Map {
      const targetId = mapId || activeMapId;
      
      if (!targetId) {
        throw new Error('No active map found. Please add a map instance first.');
      }
      
      const mapInstance = mapInstances[targetId];
      
      if (!mapInstance) {
        throw new Error(`Map with ID "${targetId}" not found.`);
      }
      
      if (mapInstance.isDestroyed) {
        throw new Error(`Map with ID "${targetId}" has been destroyed.`);
      }
      
      return mapInstance.map;
    },

    /**
     * 异步获取地图实例
     * @param mapId - 地图ID,如果不提供则等待活跃地图
     * @param timeout - 超时时间(毫秒),默认30秒
     * @returns 返回地图实例的Promise
     */
    async getMapAsync(mapId?: string, timeout: number = 30000): Promise<Map> {
      const targetId = mapId || activeMapId || 'active';
      
      // 如果地图已经存在,直接返回
      if (targetId !== 'active' && mapInstances[targetId] && !mapInstances[targetId].isDestroyed) {
        return mapInstances[targetId].map;
      }
      
      // 如果是活跃地图且已存在,直接返回
      if (targetId === 'active' && activeMapId && mapInstances[activeMapId] && !mapInstances[activeMapId].isDestroyed) {
        return mapInstances[activeMapId].map;
      }
      
      // 创建Promise等待地图初始化
      return new Promise<Map>((resolve, reject) => {
        const waitKey = targetId === 'active' ? 'active' : targetId;
        
        if (!waitingCallbacks[waitKey]) {
          waitingCallbacks[waitKey] = [];
        }
        
        // 设置超时
        const timeoutId = setTimeout(() => {
          // 从等待队列中移除这个回调
          const callbacks = waitingCallbacks[waitKey];
          if (callbacks) {
            const index = callbacks.findIndex(cb => cb.timeout === timeoutId);
            if (index !== -1) {
              callbacks.splice(index, 1);
            }
            if (callbacks.length === 0) {
              delete waitingCallbacks[waitKey];
            }
          }
          reject(new Error(`Timeout waiting for map${targetId !== 'active' ? ` with ID "${targetId}"` : ''} to be initialized after ${timeout}ms`));
        }, timeout);
        
        waitingCallbacks[waitKey].push({
          resolve,
          reject,
          timeout: timeoutId
        });
      });
    },

    /**
     * 获取地图实例信息
     * @param mapId - 地图ID
     * @returns 返回地图实例信息
     */
    getMapInfo(mapId: string): MapInstance | null {
      return mapInstances[mapId] || null;
    },

    /**
     * 获取所有地图实例
     * @returns 返回所有地图实例的数组
     */
    getAllMaps(): MapInstance[] {
      return Object.values(mapInstances).filter(instance => !instance.isDestroyed);
    },

    /**
     * 根据索引获取地图实例
     * @param index - 地图索引
     * @returns 返回地图实例
     */
    getMapByIndex(index: number): Map {
      const maps = this.getAllMaps();
      if (index < 0 || index >= maps.length) {
        throw new Error(`Map index ${index} is out of range. Available maps: ${maps.length}`);
      }
      return maps[index].map;
    },

    /**
     * 异步根据索引获取地图实例
     * @param index - 地图索引
     * @param timeout - 超时时间(毫秒),默认30秒
     * @returns 返回地图实例的Promise
     */
    async getMapByIndexAsync(index: number, timeout: number = 30000): Promise<Map> {
      return new Promise<Map>((resolve, reject) => {
        const checkMaps = () => {
          const maps = this.getAllMaps();
          if (index >= 0 && index < maps.length) {
            resolve(maps[index].map);
            return true;
          }
          return false;
        };
        
        // 立即检查一次
        if (checkMaps()) {
          return;
        }
        
        // 设置超时
        const timeoutId = setTimeout(() => {
          reject(new Error(`Timeout waiting for map at index ${index} to be available after ${timeout}ms`));
        }, timeout);
        
        // 定期检查地图是否可用
        const interval = setInterval(() => {
          if (checkMaps()) {
            clearTimeout(timeoutId);
            clearInterval(interval);
          }
        }, 100);
      });
    },

    /**
     * 设置活跃地图
     * @param mapId - 地图ID
     * @throws 如果地图不存在或已销毁则抛出错误
     */
    setActiveMap(mapId: string): void {
      const mapInstance = mapInstances[mapId];
      
      if (!mapInstance) {
        throw new Error(`Map with ID "${mapId}" not found.`);
      }
      
      if (mapInstance.isDestroyed) {
        throw new Error(`Map with ID "${mapId}" has been destroyed.`);
      }
      
      activeMapId = mapId;
      
      // 触发等待活跃地图的回调
      triggerWaitingCallbacks('active', mapInstance.map);
    },

    /**
     * 获取活跃地图ID
     * @returns 返回活跃地图ID
     */
    getActiveMapId(): string | null {
      return activeMapId;
    },

    /**
     * 检查地图是否已初始化
     * @param mapId - 地图ID,如果不提供则检查活跃地图
     * @returns 返回地图初始化状态
     */
    isMapInitialized(mapId?: string): boolean {
      const targetId = mapId || activeMapId;
      
      if (!targetId) {
        return false;
      }
      
      const mapInstance = mapInstances[targetId];
      return mapInstance ? !mapInstance.isDestroyed : false;
    },

    /**
     * 销毁地图实例
     * @param mapId - 地图ID,如果不提供则销毁活跃地图
     */
    destroyMap(mapId?: string): void {
      const targetId = mapId || activeMapId;
      
      if (!targetId) {
        return;
      }
      
      const mapInstance = mapInstances[targetId];
      
      if (mapInstance && !mapInstance.isDestroyed) {
        // 触发等待该地图的错误回调
        triggerWaitingCallbacksError(targetId, new Error(`Map with ID "${targetId}" has been destroyed`));
        
        // 如果地图实例有remove方法,调用它进行清理
        if (typeof mapInstance.map.remove === 'function') {
          try {
            mapInstance.map.remove();
          } catch (error) {
            console.warn(`Error while removing map instance ${targetId}:`, error);
          }
        }
        
        mapInstance.isDestroyed = true;
        
        // 如果销毁的是活跃地图,重新设置活跃地图
        if (activeMapId === targetId) {
          const activeMaps = this.getAllMaps();
          activeMapId = activeMaps.length > 0 ? activeMaps[0].id : null;
          
          // 触发等待活跃地图的错误回调
          triggerWaitingCallbacksError('active', new Error('Active map has been destroyed'));
        }
      }
    },

    /**
     * 销毁所有地图实例
     */
    destroyAllMaps(): void {
      // 触发所有等待回调的错误
      Object.keys(waitingCallbacks).forEach(key => {
        triggerWaitingCallbacksError(key, new Error('All maps have been destroyed'));
      });
      
      for (const mapId in mapInstances) {
        this.destroyMap(mapId);
      }
      Object.keys(mapInstances).forEach(key => delete mapInstances[key]);
      activeMapId = null;
    },

    /**
     * 清理已销毁的地图实例
     */
    cleanup(): void {
      for (const mapId in mapInstances) {
        if (mapInstances[mapId].isDestroyed) {
          delete mapInstances[mapId];
        }
      }
    },

    /**
     * 重置地图管理器状态
     * 用于测试或特殊情况下的状态重置
     */
    reset(): void {
      // 清理所有等待回调
      Object.keys(waitingCallbacks).forEach(key => {
        triggerWaitingCallbacksError(key, new Error('Map manager has been reset'));
      });
      
      this.destroyAllMaps();
      mapIdCounter = 0;
    }
  };
})();

/**
 * 提供地图实例给其他组件使用
 * @param map - MapLibre地图实例
 * @param customId - 自定义地图ID(可选)
 * @returns 返回地图ID
 */
export function useProvideMap(map: Map, customId?: string): string {
  return createMapManager.addMap(map, customId);
}

/**
 * 注入并获取地图实例(同步版本)
 * @param mapId - 地图ID,如果不提供则返回活跃地图
 * @returns 返回地图实例
 */
export function useInjectMap(mapId?: string): Map {
  return createMapManager.getMap(mapId);
}

/**
 * 异步注入并获取地图实例
 * @param mapId - 地图ID,如果不提供则等待活跃地图
 * @param timeout - 超时时间(毫秒),默认30秒
 * @returns 返回地图实例的Promise
 */
export function useInjectMapAsync(mapId?: string, timeout?: number): Promise<Map> {
  return createMapManager.getMapAsync(mapId, timeout);
}

/**
 * 获取所有地图实例
 * @returns 返回所有地图实例的数组
 */
export function useGetAllMaps(): Array<{ id: string; map: Map; createdAt: number }> {
  return createMapManager.getAllMaps().map(instance => ({
    id: instance.id,
    map: instance.map,
    createdAt: instance.createdAt
  }));
}

/**
 * 根据索引获取地图实例(同步版本)
 * @param index - 地图索引
 * @returns 返回地图实例
 */
export function useGetMapByIndex(index: number): Map {
  return createMapManager.getMapByIndex(index);
}

/**
 * 异步根据索引获取地图实例
 * @param index - 地图索引
 * @param timeout - 超时时间(毫秒),默认30秒
 * @returns 返回地图实例的Promise
 */
export function useGetMapByIndexAsync(index: number, timeout?: number): Promise<Map> {
  return createMapManager.getMapByIndexAsync(index, timeout);
}

/**
 * 设置活跃地图
 * @param mapId - 地图ID
 */
export function useSetActiveMap(mapId: string): void {
  createMapManager.setActiveMap(mapId);
}

/**
 * 获取活跃地图ID
 * @returns 返回活跃地图ID
 */
export function useGetActiveMapId(): string | null {
  return createMapManager.getActiveMapId();
}

/**
 * 检查地图是否已初始化
 * @param mapId - 地图ID,如果不提供则检查活跃地图
 * @returns 返回地图初始化状态
 */
export function useMapStatus(mapId?: string): boolean {
  return createMapManager.isMapInitialized(mapId);
}

/**
 * 销毁地图实例
 * @param mapId - 地图ID,如果不提供则销毁活跃地图
 */
export function useDestroyMap(mapId?: string): void {
  createMapManager.destroyMap(mapId);
}

/**
 * 销毁所有地图实例
 */
export function useDestroyAllMaps(): void {
  createMapManager.destroyAllMaps();
}

/**
 * 重置地图管理器
 * 主要用于测试或开发环境
 */
export function useResetMap(): void {
  createMapManager.reset();
}

概述

useMap 是一个专为 Vue3 + MapLibre 项目设计的地图实例管理工具,提供了完整的地图生命周期管理功能。该工具采用闭包设计模式,确保地图实例的安全存储和访问,支持多地图实例管理、异步获取、自动清理等功能。

核心特性

主要功能

  • 多地图实例管理:支持同时管理多个地图实例
  • 活跃地图切换:自动管理当前活跃的地图实例
  • 异步获取支持:支持异步等待地图初始化完成
  • 自动清理机制:提供完善的地图实例销毁和清理功能
  • Vue3 响应式优化:使用 markRaw 避免不必要的响应式处理
  • TypeScript 支持:完整的类型定义和类型安全

️ 安全特性

  • 实例验证:确保传入的是有效的 MapLibre 地图实例
  • 错误处理:完善的错误处理和异常捕获机制
  • 内存管理:自动清理已销毁的地图实例,防止内存泄漏
  • 超时控制:异步操作支持超时设置,避免无限等待

安装与导入

// 导入所需的函数
import {
  useProvideMap,      // 提供地图实例
  useInjectMap,       // 同步获取地图实例
  useInjectMapAsync,  // 异步获取地图实例
  useGetAllMaps,      // 获取所有地图实例
  useSetActiveMap,    // 设置活跃地图
  useDestroyMap,      // 销毁地图实例
  useMapStatus        // 检查地图状态
} from 'shared-utils/hooks/web/useMap'

基础使用方法

1. 创建和注册地图实例

<template>
  <div ref="mapContainer" class="map-container"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { Map } from 'maplibre-gl'
import { useProvideMap, useDestroyMap } from 'shared-utils/hooks/web/useMap'

const mapContainer = ref<HTMLElement>()
let mapId: string

onMounted(() => {
  // 创建地图实例
  const map = new Map({
    container: mapContainer.value!,
    style: 'https://demotiles.maplibre.org/style.json',
    center: [116.404, 39.915],
    zoom: 10
  })
  
  // 注册地图实例到管理器
  mapId = useProvideMap(map, 'main-map')
  
  console.log('地图已注册,ID:', mapId)
})

onUnmounted(() => {
  // 组件销毁时清理地图
  useDestroyMap(mapId)
})
</script>

2. 在其他组件中获取地图实例

<script setup lang="ts">
import { onMounted } from 'vue'
import { useInjectMap, useInjectMapAsync } from 'shared-utils/hooks/web/useMap'

// 方式1:同步获取(地图必须已经初始化)
onMounted(() => {
  try {
    const map = useInjectMap('main-map')
    console.log('获取到地图实例:', map)
    
    // 使用地图实例
    map.flyTo({
      center: [116.404, 39.915],
      zoom: 12
    })
  } catch (error) {
    console.error('获取地图失败:', error)
  }
})

// 方式2:异步获取(推荐)
onMounted(async () => {
  try {
    const map = await useInjectMapAsync('main-map', 10000) // 10秒超时
    console.log('异步获取到地图实例:', map)
    
    // 使用地图实例
    map.addLayer({
      id: 'my-layer',
      type: 'circle',
      source: 'my-source',
      paint: {
        'circle-radius': 5,
        'circle-color': '#007cbf'
      }
    })
  } catch (error) {
    console.error('异步获取地图失败:', error)
  }
})
</script>

高级功能

1. 多地图实例管理

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { Map } from 'maplibre-gl'
import { 
  useProvideMap, 
  useGetAllMaps, 
  useSetActiveMap,
  useGetMapByIndex 
} from 'shared-utils/hooks/web/useMap'

const mapContainer1 = ref<HTMLElement>()
const mapContainer2 = ref<HTMLElement>()

onMounted(() => {
  // 创建第一个地图
  const map1 = new Map({
    container: mapContainer1.value!,
    style: 'https://demotiles.maplibre.org/style.json',
    center: [116.404, 39.915],
    zoom: 10
  })
  
  // 创建第二个地图
  const map2 = new Map({
    container: mapContainer2.value!,
    style: 'https://demotiles.maplibre.org/style.json',
    center: [121.473, 31.230],
    zoom: 10
  })
  
  // 注册多个地图实例
  const mapId1 = useProvideMap(map1, 'beijing-map')
  const mapId2 = useProvideMap(map2, 'shanghai-map')
  
  // 获取所有地图实例
  const allMaps = useGetAllMaps()
  console.log('所有地图实例:', allMaps)
  
  // 设置活跃地图
  useSetActiveMap('shanghai-map')
  
  // 根据索引获取地图
  const firstMap = useGetMapByIndex(0)
  console.log('第一个地图:', firstMap)
})
</script>

2. 地图状态检查和错误处理

<script setup lang="ts">
import { 
  useMapStatus, 
  useInjectMapAsync, 
  useGetActiveMapId 
} from 'shared-utils/hooks/web/useMap'

// 检查地图状态
const checkMapStatus = () => {
  const isInitialized = useMapStatus('main-map')
  console.log('地图是否已初始化:', isInitialized)
  
  const activeMapId = useGetActiveMapId()
  console.log('当前活跃地图ID:', activeMapId)
}

// 安全的地图获取
const safeGetMap = async () => {
  try {
    // 设置较短的超时时间
    const map = await useInjectMapAsync('main-map', 5000)
    
    // 检查地图是否可用
    if (map && !map.isDestroyed) {
      console.log('地图可用,执行操作...')
      // 执行地图操作
    }
  } catch (error) {
    if (error.message.includes('Timeout')) {
      console.error('地图获取超时,请检查地图是否正确初始化')
    } else {
      console.error('获取地图失败:', error.message)
    }
  }
}
</script>

3. 组件化地图管理

// MapProvider.vue - 地图提供者组件
<template>
  <div class="map-provider">
    <div ref="mapContainer" class="map-container"></div>
    <slot :map-id="mapId" :map-ready="mapReady"></slot>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { Map } from 'maplibre-gl'
import { useProvideMap, useDestroyMap } from 'shared-utils/hooks/web/useMap'

interface Props {
  mapId?: string
  mapOptions?: any
}

const props = withDefaults(defineProps<Props>(), {
  mapId: 'default-map',
  mapOptions: () => ({
    style: 'https://demotiles.maplibre.org/style.json',
    center: [116.404, 39.915],
    zoom: 10
  })
})

const mapContainer = ref<HTMLElement>()
const mapId = ref<string>('')
const mapReady = ref(false)

onMounted(() => {
  const map = new Map({
    container: mapContainer.value!,
    ...props.mapOptions
  })
  
  map.on('load', () => {
    mapReady.value = true
  })
  
  mapId.value = useProvideMap(map, props.mapId)
})

onUnmounted(() => {
  if (mapId.value) {
    useDestroyMap(mapId.value)
  }
})
</script>

// MapConsumer.vue - 地图消费者组件
<template>
  <div class="map-consumer">
    <button @click="addMarker">添加标记</button>
    <button @click="flyToLocation">飞行到位置</button>
  </div>
</template>

<script setup lang="ts">
import { useInjectMapAsync } from 'shared-utils/hooks/web/useMap'

interface Props {
  mapId: string
}

const props = defineProps<Props>()

const addMarker = async () => {
  try {
    const map = await useInjectMapAsync(props.mapId)
    
    // 添加标记逻辑
    map.addSource('marker-source', {
      type: 'geojson',
      data: {
        type: 'Feature',
        geometry: {
          type: 'Point',
          coordinates: [116.404, 39.915]
        }
      }
    })
    
    map.addLayer({
      id: 'marker-layer',
      type: 'circle',
      source: 'marker-source',
      paint: {
        'circle-radius': 8,
        'circle-color': '#ff0000'
      }
    })
  } catch (error) {
    console.error('添加标记失败:', error)
  }
}

const flyToLocation = async () => {
  try {
    const map = await useInjectMapAsync(props.mapId)
    
    map.flyTo({
      center: [121.473, 31.230],
      zoom: 12,
      duration: 2000
    })
  } catch (error) {
    console.error('飞行到位置失败:', error)
  }
}
</script>

最佳实践

1. 错误处理策略

// 创建一个地图操作的包装函数
const safeMapOperation = async (
  mapId: string, 
  operation: (map: Map) => void | Promise<void>
) => {
  try {
    const map = await useInjectMapAsync(mapId, 10000)
    await operation(map)
  } catch (error) {
    console.error(`地图操作失败 (${mapId}):`, error)
    // 可以添加用户友好的错误提示
    ElMessage.error('地图操作失败,请稍后重试')
  }
}

// 使用示例
safeMapOperation('main-map', (map) => {
  map.addLayer({
    id: 'my-layer',
    type: 'fill',
    source: 'my-source'
  })
})

2. 性能优化

// 使用 computed 缓存地图状态
import { computed } from 'vue'

const mapStatus = computed(() => {
  return useMapStatus('main-map')
})

// 避免频繁的地图获取
let cachedMap: Map | null = null

const getCachedMap = async (mapId: string) => {
  if (!cachedMap || cachedMap.isDestroyed) {
    cachedMap = await useInjectMapAsync(mapId)
  }
  return cachedMap
}

3. 内存管理

// 在路由切换时清理地图
import { onBeforeRouteLeave } from 'vue-router'

onBeforeRouteLeave(() => {
  // 清理当前页面的地图实例
  useDestroyMap('current-page-map')
})

// 在应用关闭时清理所有地图
import { onBeforeUnmount } from 'vue'
import { useDestroyAllMaps } from 'shared-utils/hooks/web/useMap'

onBeforeUnmount(() => {
  useDestroyAllMaps()
})

常见问题解决

1. 地图获取失败

// 问题:地图实例未找到
// 解决:使用异步获取并设置合理的超时时间
try {
  const map = await useInjectMapAsync('my-map', 15000)
} catch (error) {
  if (error.message.includes('not found')) {
    console.log('地图实例未注册,请检查地图ID')
  } else if (error.message.includes('Timeout')) {
    console.log('地图初始化超时,请检查网络连接')
  }
}

2. 地图已销毁错误

// 问题:尝试使用已销毁的地图实例
// 解决:在使用前检查地图状态
const useMapSafely = async (mapId: string) => {
  if (!useMapStatus(mapId)) {
    throw new Error('地图实例不可用')
  }
  
  return await useInjectMapAsync(mapId)
}

3. 多地图实例冲突

// 问题:多个地图实例使用相同ID
// 解决:使用唯一的地图ID
const generateUniqueMapId = () => {
  return `map_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
}

const mapId = generateUniqueMapId()
useProvideMap(map, mapId)

总结

useMap 地图管理工具为 Vue3 + MapLibre 项目提供了完整的地图实例管理解决方案。通过合理使用其提供的 API,可以:

  • 简化地图管理:统一的地图实例存储和访问接口
  • 提高代码安全性:完善的错误处理和类型检查
  • 优化性能:避免重复创建地图实例,合理的内存管理
  • 增强开发体验:异步支持、TypeScript 类型提示

建议在实际项目中结合具体业务需求,选择合适的 API 组合使用,并遵循最佳实践以确保代码的稳定性和可维护性。


提示:本文档基于 Vue3 + MapLibre + TypeScript 技术栈,如果您使用的是其他技术栈,请根据实际情况调整代码示例。

相关资源

  • MapLibre GL JS 官方文档
  • Vue3 Composition API 文档
  • TypeScript 官方文档

你可能感兴趣的:(Mapbox和Maplibre,vue.js,前端,javascript)