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

如何通过AJAX获取PHP生成的JS脚本并执行?谷歌地图标记优化问题

解决Google Maps API大量标记导致页面无响应及动态脚本加载失效问题

先帮你解决当前测试脚本的问题,再给你梳理正确的视口标记加载方案。

一、当前测试脚本失效的原因及修复

你的PHP脚本返回了包裹在<script>标签里的代码,但eval()只会执行纯JavaScript代码,不会解析HTML的<script>标签,这就是为什么你的代码没生效。

修改后的PHP脚本(fjack.php)

去掉多余的<script>标签,直接返回纯JS代码:

<?php
echo "function me(){ document.getElementById('demo').innerHTML='ITS WORKING'; } me();";
?>

前端代码优化

其实你不需要把代码插入到#script元素里,直接eval返回的内容即可,或者更规范的方式是创建<script>元素插入到DOM中(比eval更安全):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script>
function loadDoc() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      // 方法1:使用eval(简单但不推荐,有安全风险)
      // eval(this.responseText);
      
      // 方法2:创建script元素插入DOM(更安全规范)
      const script = document.createElement('script');
      script.textContent = this.responseText;
      document.body.appendChild(script);
    }
  };
  xhttp.open("GET", "fjack.php", true);
  xhttp.send();
}
</script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Test Script Load</title>
</head>
<body>
<div onclick="loadDoc();"> click </div>
<div id="demo"></div>
</body>
</html>

这样修改后,点击按钮就能看到demo元素显示"ITS WORKING"了。

二、Google Maps视口内标记加载的正确实现思路

你的核心需求是只加载当前地图视口和缩放级别内的标记,这是解决大量标记导致页面卡顿的最佳方案,下面是完整的实现步骤:

1. 前端监听地图视口变化

首先初始化Google Maps,然后监听bounds_changed和zoom_changed事件(注意防抖,避免频繁触发请求):

let map;
let debounceTimer;

function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: -34.397, lng: 150.644},
    zoom: 8
  });

  // 监听视口变化,防抖处理
  map.addListener('bounds_changed', function() {
    clearTimeout(debounceTimer);
    debounceTimer = setTimeout(fetchMarkersInViewport, 300);
  });

  // 初始加载一次当前视口的标记
  fetchMarkersInViewport();
}

function fetchMarkersInViewport() {
  const bounds = map.getBounds();
  const zoom = map.getZoom();
  // 获取视口的西南和东北坐标
  const sw = bounds.getSouthWest();
  const ne = bounds.getNorthEast();

  // 发送AJAX请求给PHP,传递视口参数
  const xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      const markersData = JSON.parse(this.responseText);
      // 清除旧标记(如果需要)
      clearExistingMarkers();
      // 创建新标记
      markersData.forEach(createMarker);
    }
  };
  // 构造GET参数:西南lat、西南lng、东北lat、东北lng、缩放级别
  const params = `sw_lat=${sw.lat()}&sw_lng=${sw.lng()}&ne_lat=${ne.lat()}&ne_lng=${ne.lng()}&zoom=${zoom}`;
  xhttp.open("GET", "fetch_markers.php?" + params, true);
  xhttp.send();
}

// 存储所有标记的数组,方便后续清除
let markersArray = [];

function createMarker(markerInfo) {
  const marker = new google.maps.Marker({
    position: {lat: markerInfo.lat, lng: markerInfo.lng},
    map: map,
    title: markerInfo.title
  });
  markersArray.push(marker);
}

function clearExistingMarkers() {
  markersArray.forEach(marker => marker.setMap(null));
  markersArray = [];
}

2. PHP脚本处理请求并返回标记数据

fetch_markers.php需要接收视口参数,查询数据库中在该范围内的地点,然后以JSON格式返回数据(不要返回JS函数,直接返回数据更灵活):

<?php
// 连接数据库(示例,根据你的实际情况修改)
$conn = mysqli_connect("localhost", "username", "password", "your_db");

// 获取前端传递的参数
$sw_lat = $_GET['sw_lat'];
$sw_lng = $_GET['sw_lng'];
$ne_lat = $_GET['ne_lat'];
$ne_lng = $_GET['ne_lng'];
$zoom = $_GET['zoom'];

// 安全的预处理查询(避免SQL注入)
$stmt = $conn->prepare("SELECT lat, lng, title FROM markers WHERE lat BETWEEN ? AND ? AND lng BETWEEN ? AND ?");
$stmt->bind_param("dddd", $sw_lat, $ne_lat, $sw_lng, $ne_lng);
$stmt->execute();
$result = $stmt->get_result();

$markers = [];
while ($row = mysqli_fetch_assoc($result)) {
  $markers[] = [
    'lat' => (float)$row['lat'],
    'lng' => (float)$row['lng'],
    'title' => $row['title']
  ];
}

// 返回JSON格式的数据
header('Content-Type: application/json');
echo json_encode($markers);

$stmt->close();
mysqli_close($conn);
?>

3. 关键注意事项

  • 防抖处理:地图视口变化会频繁触发事件,用setTimeout防抖可以避免过多的AJAX请求,减轻服务器压力。
  • 空间查询优化:如果你的数据库支持空间索引(比如MySQL的SPATIAL索引),一定要给lat和lng字段创建空间索引,大幅提升查询效率。
  • 标记管理:维护一个标记数组,在加载新标记前清除旧标记,避免地图上堆积过多标记。
  • 安全问题:必须使用预处理语句处理SQL查询,避免SQL注入风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:06:27