SolidJS + Leaflet地图选点故障:handlePicker无法添加标记选点
SolidJS集成Leaflet地图选点功能失效的解决方案
一、修复现有代码的问题
你的代码存在几个关键问题,导致handlePicker函数无法触发:
地图类型声明错误
你将map声明为L.TileLayer | undefined,但buildMap返回的是Leaflet的Map实例,类型不匹配会导致后续事件绑定逻辑失效。修正类型:let map: L.Map | undefined;Effect依赖缺失导致事件未绑定
createEffect的依赖数组为空,当onMount中map被赋值后,Effect不会重新执行,因此点击事件从未绑定到地图上。可以直接在onMount中绑定事件(onMount在地图创建后执行),或者给Effect添加map依赖:onMount(() => { map = buildMap(mapDiv); map.on("click", handlePicker); // 组件卸载时移除事件监听 return () => map?.off("click", handlePicker); });或者保留Effect并补充依赖:
createEffect(() => { if (map) { map.on("click", handlePicker); return () => map.off("click", handlePicker); } }, [map]);标记拖拽事件优化
拖拽事件回调中,直接使用标记实例的getLatLng()获取位置更准确:pin.on('drag', () => { setLatlng(pin.getLatLng()); });
修复后的核心代码片段:
export default function PublishPage() { const [latlng, setLatlng] = createSignal<LatLng>() let mapDiv: HTMLDivElement; let map: L.Map | undefined; let pin: L.Marker | undefined; onMount(() => { map = buildMap(mapDiv); map.on("click", handlePicker); return () => map?.off("click", handlePicker); }) function handlePicker(ev: L.LeafletMouseEvent) { const selectedLatLng = ev.latlng; setLatlng(selectedLatLng); if (pin) { pin.setLatLng(selectedLatLng); } else { pin = L.marker(selectedLatLng, { riseOnHover: true, draggable: true }); pin.addTo(map!); pin.on('drag', () => { setLatlng(pin!.getLatLng()); }); } } // 其余代码不变... }
二、使用适配SolidJS的Leaflet库
如果想更贴合SolidJS的响应式开发模式,推荐使用solid-leaflet——专门为SolidJS封装的Leaflet组件库,无需手动操作DOM和事件绑定,用Solid信号即可管理地图状态。
基本使用示例(实现选点功能)
- 安装依赖:
npm install solid-leaflet leaflet - 引入Leaflet样式(入口文件或组件中):
import "leaflet/dist/leaflet.css"; - 实现选点组件:
import { Title } from "@solidjs/meta"; import { MapContainer, TileLayer, Marker, useMapEvents } from "solid-leaflet"; import { FaSolidLocationCrosshairs } from "solid-icons/fa"; import { createSignal } from "solid-js"; export default function PublishPage() { const [position, setPosition] = createSignal([51.505, -0.09] as [number, number]); // 监听地图点击事件 const MapClickHandler = () => { useMapEvents({ click(e) { setPosition([e.latlng.lat, e.latlng.lng]); }, }); return null; }; return ( <div> <Title>Publish App</Title> <div class="h-[90vh] flex items-center justify-center text-[#222]"> <div class="shadow border rounded-lg p-6 w-[80dvh]"> <div class="text-center"> <h2 class="text-3xl font-bold">Publish</h2> </div> <div class="my-4"> <div class="w-full h-[20rem] rounded-lg"> <MapContainer center={position()} zoom={13} style={{ height: "100%", width: "100%" }}> <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> <Marker position={position()} draggable={true} onDragend={(e) => setPosition([e.target.getLatLng().lat, e.target.getLatLng().lng])} /> <MapClickHandler /> </MapContainer> </div> <div class="mt-2 flex justify-end"> <button class="border shadow px-4 py-2"> <FaSolidLocationCrosshairs /> </button> </div> </div> </div> </div> </div> ); }
该库完全遵循SolidJS响应式规则,用信号驱动地图状态,无需手动管理事件绑定和生命周期,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Happer64Bit
相关产品推荐
相关产品推荐

