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

勾选复选框后Leaflet标记无法更新的问题求助

Leaflet标记不随复选框筛选更新的解决方法

问题背景

我已经实现了根据勾选的复选框返回对应筛选数据,console.log里的筛选结果会正常变化,但地图上的Leaflet标记完全没更新。推测是复选框的change事件监听器没触发标记的重新渲染,求解决办法。

解决思路

  • 数组filteredEntries更新不会自动触发Leaflet标记更新,因为标记是一次性添加到地图实例的
  • 必须保存所有标记的引用,每次筛选前先移除旧标记
  • 将添加标记的逻辑封装成独立函数,筛选完成后重新调用生成新标记

修改后的完整代码

import { maps, customOptions } from "../leaflet.js";

let entries = [];
let filteredEntries = [];
// 新增:存储所有标记的引用,用于批量清除
let markers = [];

async function bootThis() {
    const endpoint = 'ENDPOINT';

    const boot = 
    `
    fragment BootQuery on test_test_Entry {
        id
        crops
        country
        year
        testType
        lon
        lat
        specsTrial
        entryStatus
    }
    query {
        boot: entries(section: "test") {
            title
            ...BootQuery
        }
    }
    `

    fetch(endpoint, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer TOKEN'
           },
        body: JSON.stringify({ query: boot })
        })
        .then(response => response.json()) // 修复:原代码缺失JSON解析步骤
        .then(data => {
            document.querySelector( '#resultsNumber > p').innerHTML = `${data.data['boot'].length}`

            // 获取所有国家复选框
            const countriesCheckboxes = document.querySelectorAll('input[type="checkbox"][name="countries"]');
            const countriesCheckboxesArray = Array.from(countriesCheckboxes);

            // 初始化数据
            entries = data.data['boot']
            filteredEntries = entries

            // 首次渲染标记
            renderMarkers();

            // 复选框筛选事件监听
            countriesCheckboxesArray.forEach(checkbox => {
                checkbox.addEventListener('change', () => {
                    const values = countriesCheckboxesArray
                    .filter(checkbox => checkbox.checked)
                    .map(checkbox => checkbox.value)
                    
                    // 处理无勾选的情况:显示所有数据
                    filteredEntries = values.length ? entries.filter(feature => values.includes(feature.country)) : entries;
                    console.log(filteredEntries);
                    
                    // 重新渲染标记
                    renderMarkers();
                });
            });
        })
        .catch(error => {
            console.error(error)
        })
};

// 封装渲染标记的函数:先清旧标记,再添新标记
function renderMarkers() {
    // 移除所有旧标记
    markers.forEach(marker => {
        maps.removeLayer(marker);
    });
    markers = []; // 清空标记数组

    // 添加新标记并保存引用
    filteredEntries.forEach((feature) => {
        const keys = Object.keys(feature);
        const marker = L.marker([feature.lat, feature.lon]).addTo(maps).bindPopup(
            `
            <strong>${feature.title}</strong>
            <br/>
            <br/>
            <p><strong>${findKey(keys, 'crops')}: </strong>${feature.crops}</p>
            <p><strong>${findKey(keys, 'country')}: </strong>${feature.country}</p>
            <p><strong>${findKey(keys, 'testType')}: </strong>${feature.testType}</p>
            <p><strong>${findKey(keys, 'year')}: </strong>${feature.year}</p>
            <p><strong>${findKey(keys, 'entryStatus')}: </strong>${feature.entryStatus}</p>
            <br/>
            <p><strong>${findKey(keys, 'specsTrial')}: </strong>${feature.specsTrial}</p>
            `, customOptions);
        
        markers.push(marker);
    });
}

function convertCountry(country) {
    if(country === 'BE') {
        return 'Belgium'
    }
    else if(country === 'NL') {
        return 'The Netherlands'
    }
    else if(country === 'FR') {
        return 'France'
    }
    else if(country === 'IT') {
        return 'Italy'
    }
    else {
        return 'Hungary'
    };
};

function findKey(array, key) {
    const look = array.find(feature => feature === key)
    return look.charAt(0).toUpperCase() + look.slice(1).replace(/[A-Z]/g, 
    function(match) {
        return match === match.toUpperCase() ? ' ' + match.toLowerCase() : match;
    });
};

await bootThis();

关键修改说明

  • 新增markers数组存储所有标记引用,实现批量清除旧标记
  • 抽离renderMarkers函数统一处理标记的清除与添加逻辑
  • 在初始化和筛选事件中调用renderMarkers,确保数据与标记同步
  • 修复原代码中fetch缺少response.json()的隐性bug
  • 处理无复选框勾选的边界情况,此时显示所有标记

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 00:24:51