当前位置: 首页 > news >正文

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> = {};// 私有变量:当前活跃的地图IDlet 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: stringonMounted(() => {// 创建地图实例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?: stringmapOptions?: 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 = nullconst 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 官方文档

文章转载自:
http://barbola.zekgq.cn
http://britska.zekgq.cn
http://bioclean.zekgq.cn
http://automania.zekgq.cn
http://angst.zekgq.cn
http://barnacles.zekgq.cn
http://aiche.zekgq.cn
http://beerburst.zekgq.cn
http://chessboard.zekgq.cn
http://chatelain.zekgq.cn
http://caravaggiesque.zekgq.cn
http://belmopan.zekgq.cn
http://champaign.zekgq.cn
http://capcom.zekgq.cn
http://bedesman.zekgq.cn
http://aarnet.zekgq.cn
http://bolton.zekgq.cn
http://autorotate.zekgq.cn
http://aauw.zekgq.cn
http://bikky.zekgq.cn
http://bride.zekgq.cn
http://aggiornamento.zekgq.cn
http://albion.zekgq.cn
http://blatherskite.zekgq.cn
http://arlington.zekgq.cn
http://buffet.zekgq.cn
http://botan.zekgq.cn
http://adiaphoresis.zekgq.cn
http://cadmean.zekgq.cn
http://carlowitz.zekgq.cn
http://www.dtcms.com/a/281765.html

相关文章:

  • 牛客:HJ22 汽水瓶[华为机考][数字处理]
  • 基于Sentinel-1雷达数据的洪水动态监测(附完整GEE代码)
  • 深入理解红锁
  • Vue3入门-指令补充
  • 学习C++、QT---26(QT中实现记事本项目实现文件路径的提示、C++类模板、记事本的行高亮的操作的讲解)
  • 面向对象与面向过程、函数式编程
  • C++回顾 Day8
  • 【时时三省】(C语言基础)通过指针引用多维数组
  • 【09】MFC入门到精通——MFC 属性页对话框的 CPropertyPage类 和 CPropertySheet 类
  • burpsuite使用中遇到的一些问题(bp启动后浏览器无法连接)/如何导入证书
  • css实现烧香效果
  • 20.如何在 Python 字典中找到最小值或最大值的键?
  • 【卡尔曼滤波第六期】集合变换卡尔曼滤波 ETKF
  • 【Linux庖丁解牛】— 保存信号!
  • HTML网页结构(基础)
  • 【linux V0.11】init/main.c
  • 函数指针与指针函数练习讲解
  • 9、线程理论1
  • HostVDS 云服务器测评:平价入门、流媒体解锁全美、表现稳定
  • 暑假Python基础整理 --异常处理及程序调试
  • Redis 中的持久化机制:RDB 与 AOF
  • Java之Stream其二
  • 第二章 OB 存储引擎高级技术
  • 数学金融与金融工程:学科差异与选择指南
  • 【AI News | 20250714】每日AI进展
  • 为 Git branch 命令添加描述功能
  • 将 Vue 3 + Vite + TS 项目打包为 .exe 文件
  • 711SJBH构建制造业信息化人才培训体系的对策-开题报告
  • 21-C#的委托简单使用-1
  • Datawhale 25年7月组队学习coze-ai-assistant Task1学习笔记:动手实践第一个AI Agent—英伦生活口语陪练精灵