使用Vue响应式数据ref()控制leaflet图层, 缩放时出现Bug:annot read properties of null (reading ‘_latLngToNewLayerPoint‘

做成的效果为: 规划路线时可在地图添加起始点, 终点, 途径点

主要逻辑是通过一个数组记录每个点所在的图层, 然后点击增删图标来实现对对应图标的新增删除. 

问题

        因为平常一般都是用响应式数据, 所以把数组定义成ref([]). 新增图标时没什么问题, 但是当删除某个图标后, 进行地图缩放时后面的图标直接乱跑, 并且控制台报错chunk-6WXMTNSE.js?v=11499401:5166 Uncaught TypeError: Cannot read properties of null (reading '_latLngToNewLayerPoint'). 这个错误一般是对已经移除的图层进行操作是才会出现, 排查时发现从ref([])中取出的对象是Proxy(NewClass), 怀疑是响应式数据的原因, 最后改成使用普通数组后解决.

部分代码如下: 

定义参数

const routePoints = ref([]);
let layerArray = []
const mapRef = ref()
let mapInstance // 地图实例

删除某个途径点方法

// 删除途径点
function removeRoutePoint(index) {
  let layer = layerArray[index];
  if(layer && mapInstance.hasLayer(layer)) {
    mapInstance.removeLayer(layer)
  }
  layerArray.splice(index, 1)
  routePoints.value.splice(index, 1)
}

添加途径点

// 途径点选中数据时
const handleInputConfirm = (index, val) => {
  console.log(index, val)
  let selected = searchOptions.value.find(item=>item.value == val);
  
  routePoints.value[index].inputVisible = false;
  routePoints.value[index].name = selected.label
  // 设置点
  let mapinfo = selected.mapinfo
 
  let featureGroup =  layerArray[index];
  if (mapInstance && featureGroup && mapInstance.hasLayer(featureGroup)) {
    mapInstance.removeLayer(featureGroup)
  }
  featureGroup = L.featureGroup().addTo(mapInstance);
  if(featureGroup){
    const icon = new L.Icon({
      iconUrl: locationIcon,
      iconAnchor: [12, 41],
    })
    L.marker(mapinfo, { icon :icon }).addTo(featureGroup).bindTooltip('途径点'+index, {
            offset: L.point([0, -30]),
            direction: "top",
            permanent: true
        }).openTooltip();
    layerArray[index] = featureGroup;
  };
}

页面代码

<div class="h-full flex">
    <div class="flex-none flex flex-col mx-2 my-4 p-2 legend_message bg-white w-[400px]">
      <div class="flex-none">
        <div class="title">
          路线配置
        </div>
        <div class="title_message">
          起止点设置
        </div>
        <Form :label-col="{ style: { width: '70px', textAlign: 'left', margin: '0' } }" style="margin-top: 20px;">
          <FormItem  label="起始点:">
            <Select
              v-model:value="searchStartValue"
              show-search
              placeholder="请输入起始点"
              :options="searchStartOptions"
              :filter-option="filterStartOption"
              @select="handleStartSelect"
              @search="searchStartpoint"
            ></Select>
          </FormItem>
          <FormItem  label="终点:">
            <Select
              v-model:value="searchEndValue"
              show-search
              placeholder="请输入终点"
              :options="searchEndOptions"
              :filter-option="filterEndOption"
              @select="handleEndSelect"
              @search="searchEndpoint"
            ></Select>
          </FormItem>
        </Form>
        <Button type="primary" @click="choose">选点</Button>
        <Button type="primary" @click="submit">提交</Button>
      </div>
      <div class="flex-none">
        <div class="title_message">
          路线规划
        </div>
        <Timeline style="margin-top: 20px;">
          <TimelineItem v-for="(route, index) in routePoints" :key="index">
            <Select
              ref="inputRef"
              v-if="route.inputVisible && index!=0 && index != routePoints.length-1"
              v-model:value="route.name"
              show-search
              placeholder="请输入终点"
              :options="searchOptions"
              :filter-option="filterEndOption"
              @select="handleInputConfirm(index, route.name)"
              @search="searchPoint"
              size="small"
              :style="{ width: '250px' }"
            ></Select>
            <a-tag v-else style="background: #fff;" @click="showInput(index)">
              <plus-outlined />
              {{route.name}}
            </a-tag>

            <div style="float: right;gap: 8px;" >
              <!-- <FormOutlined style="margin-right: 10px;" @click=""/> -->
              <PlusCircleOutlined  @click="addRoutePoint(index)" v-if="index != routePoints.length-1"/>
              <MinusCircleOutlined style="margin-left: 10px" @click="removeRoutePoint(index)" v-if="index != routePoints.length-1"/>
            </div>
          </TimelineItem>
        </Timeline>
      </div>
      <div class="flex-none" style="text-align: right;">
        <span >
            <a-button type="primary" @click="preStep">
              上一步
            </a-button>
          </span>
          <span class="ml-2" >
            <a-button type="primary" @click="nextStep">
              下一步
            </a-button>
          </span>
      </div>
    </div>
    <div class="legend_message ml-2 flex grow mx-2 my-4 ">
      <MapView ref="mapRef" @after-init="handleMapInit"/>
    </div>
  </div>

本人也是前端菜鸡, 具体原因也不清楚, 有清楚的大佬还望告知一声, 希望能学习一下. 活到老, 学到老😊

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值