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

如何阻止Ionic React中Leaflet弹窗内的复制函数在地图渲染时自动触发

问题原因

  1. 你当前的写法在拼接弹窗HTML字符串时直接执行了writeToClipboard(part, id),函数会在图层渲染遍历的阶段就批量触发,不是点击按钮时才执行,这是直接导致崩溃的核心原因。
  2. Leaflet的bindPopup方法接收的是原生HTML字符串,内嵌的onclick事件只能访问全局作用域下的方法,无法直接调用React组件内部定义的函数,所以常规的React箭头函数包装写法不生效。

解决方案

步骤1:将复制方法挂载到全局作用域

用useEffect在组件挂载时把复制方法挂到window上,卸载时清理避免内存泄漏。

步骤2:修正弹窗HTML的事件绑定写法

用模板字符串拼接弹窗内容,把参数以字符串形式传入全局方法的调用语句中,不要直接执行函数。

额外优化

你当前给两个GeoJSON图层绑定了同一个ref,后挂载的图层会覆盖前一个的ref引用,调用resetStyle时只会作用到最后一个图层,建议要么把两个图层数据合并成一个GeoJSON,要么分开定义两个ref。


修改后完整代码

import { useState, useRef, useMemo, useEffect } from 'react';
import { MapContainer, LayersControl, TileLayer, GeoJSON } from 'react-leaflet';
import { Clipboard } from '@capacitor/clipboard';

// 请自行补充position、zoom、PL、WWD等缺失的变量定义

function LeafletMap() {
    const [map, setMap] = useState(null)
    const geoJsonRefPL = useRef();
    const geoJsonRefWWD = useRef();
  
    useEffect(() => {
      // 挂载全局复制方法
      window.writeToClipboard = async (part, id) => {
        const copyText = JSON.stringify(part.concat(id));
        await Clipboard.write({
          string: copyText
        });
      };
      // 卸载时清理
      return () => {
        delete window.writeToClipboard;
      };
    }, []);
  
    const onEachClick = (info, layer) => {
      const part = info.properties.Objekt_ID
      const id = info.properties.FID_
  
      // 修正弹窗拼接逻辑,用模板字符串拼接函数调用语句
      layer.bindPopup(
        `Objekt ID: <b>${part}</b><br>Abschnitt ID: <b>${id}</b><br><button onclick="window.writeToClipboard('${part}', '${id}')">Copy to Clipboard</button>`
      );
      
      layer.on({ click: handleFeatureClick });
    };
  
    const handleFeatureClick = (e) => {
      // 两个图层都重置样式
      geoJsonRefPL.current?.resetStyle();
      geoJsonRefWWD.current?.resetStyle();
  
      const layer = e.target;
      layer.setStyle({ color: "red" });
    };
  
  
    const displayMap = useMemo(
      () => (
        <MapContainer
          center={position}
          zoom={zoom}
          scrollWheelZoom={false}
          whenCreated={setMap}>
          <LayersControl position="topright">
            <LayersControl.BaseLayer checked name="OpenStreetMap - Karte">
              <TileLayer
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png"
              />
            </LayersControl.BaseLayer>
            <LayersControl.BaseLayer name="Esri - Satellit">
              <TileLayer
                attribution='Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
                url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
              />
            </LayersControl.BaseLayer>
          </LayersControl>

          <GeoJSON data={PL.features} onEachFeature={onEachClick} ref={geoJsonRefPL}/>
          <GeoJSON data={WWD.features} onEachFeature={onEachClick} ref={geoJsonRefWWD}/>
        </MapContainer>
      ),
      [],
    )
  
    window.dispatchEvent(new Event('resize'));
  
    return (
      <div>
        {displayMap}
      </div>
    )
  }
  
export { LeafletMap }

内容的提问来源于stack exchange,提问作者jonsken

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 07:54:06