如何在SvelteKit中为未激活区块加载MapKit地图?
解决Svelte模态组件中MapKit初始化失败的问题
问题描述
构建带MapKit的模态组件时,因组件初始处于未激活状态($display为false),onMount执行时#map元素尚未渲染,导致MapKit初始化报错:
[MapKit] 'parent' must either be a DOM element or its ID.
原代码:
<script> import { onMount } from 'svelte'; import { display } from '$lib/store.js'; // 当前值为false onMount(() => { mapkit.init({ authorizationCallback: function (done) { fetch('/api/gettoken') .then((response) => response.json()) .then(done); } }); let map = new mapkit.Map('map'); } </script> {#if $display} <div class="parent" on:click|self={disable}> <div class="child" in:fly={{ y: 200, duration: 100 }}> <div id="map" /> </div> </div> {/if}
解决方案
核心思路是等到模态组件渲染($display变为true)且#map元素存在时,再创建Map实例,同时保证MapKit只初始化一次:
修改后的代码:
<script> import { onMount, tick } from 'svelte'; import { display } from '$lib/store.js'; let map = null; let mapkitInitialized = false; onMount(() => { // 仅初始化一次MapKit mapkit.init({ authorizationCallback: done => { fetch('/api/gettoken') .then(res => res.json()) .then(done); } }); mapkitInitialized = true; }); // 监听display状态,满足条件时创建地图 $: if ($display && mapkitInitialized && !map) { // 等待DOM更新完成,确保#map已渲染 (async () => { await tick(); map = new mapkit.Map('map'); })(); } // 关闭模态时销毁地图,释放资源 $: if (!$display && map) { map.destroy(); map = null; } function disable() { $display = false; } </script> {#if $display} <div class="parent" on:click|self={disable}> <div class="child" in:fly={{ y: 200, duration: 100 }}> <!-- 给地图容器设置宽高,确保MapKit能正常渲染 --> <div id="map" style="width: 100%; height: 400px;" /> </div> </div> {/if}
关键说明
- MapKit初始化时机:放在
onMount中仅执行一次,避免重复初始化导致的问题 - DOM元素检查:用
await tick()确保#map元素已完成渲染,再创建Map实例,解决找不到父元素的报错 - 状态监听:通过Svelte的反应式语句
$:监听$display变化,动态创建/销毁地图实例,优化资源占用 - 容器样式:给
#map设置明确的宽高,否则MapKit可能无法正常显示地图
内容的提问来源于stack exchange,提问作者R Barnes
相关产品推荐
相关产品推荐

