0

0

解决EJS模板中Mapbox无法运行的JSON数据传递问题

花韻仙語

花韻仙語

发布时间:2025-11-22 22:49:02

|

817人浏览过

|

来源于php中文网

原创

解决EJS模板中Mapbox无法运行的JSON数据传递问题

本文旨在解决在ejs模板中集成mapbox时,因json数据传递不当导致的“cannot read properties of undefined”错误。核心问题在于将json字符串错误地作为javascript字符串字面量嵌入,而非直接作为可解析的javascript对象。通过采用ejs的非转义输出标签``,可以直接将json字符串注入为有效的javascript对象,从而使mapbox能够正确访问数据并初始化地图。

EJS模板中Mapbox集成的数据传递陷阱与解决方案

在Web开发中,将后端数据动态地传递给前端JavaScript库进行渲染是常见需求。然而,在使用EJS(Embedded JavaScript)模板引擎与Mapbox等客户端JavaScript库集成时,如果数据传递方式不当,很容易遇到诸如“Cannot read properties of undefined”之类的错误。本文将深入探讨这一问题,并提供一个清晰的解决方案。

问题描述:Mapbox无法访问EJS中传递的JSON数据

当尝试在EJS模板中嵌入Mapbox地图,并使用后端传递的营地(campground)数据来定位地图中心和标记时,可能会遇到以下错误:

Uncaught TypeError: Cannot read properties of undefined (reading 'coordinates') at showPageMap.js:5:33

这个错误表明在showPageMap.js文件中,尝试访问campground.geometry.coordinates时,campground对象或其geometry属性是undefined,导致无法读取coordinates。

错误的EJS数据嵌入方式

通常,为了将服务器端的JavaScript对象传递到客户端,我们会使用JSON.stringify()将其转换为JSON字符串,然后在EJS模板中嵌入。一个常见的错误做法是将其用引号包裹,如下所示:

show.ejs (错误示例):

<script>
    const mapToken = '<%=process.env.MAPBOX_TOKEN%>';
    const campground = '<%= JSON.stringify(campground) %>'; // 问题所在:被引号包裹
</script>
<div id="map" style="width: 100%; height: 500px;"></div>
<script src="/javascripts/showPageMap.js"></script>

在上述代码中,const campground = ''; 这行代码的本意是想将campground对象转换为JSON字符串,然后让JavaScript将其解析为一个对象。然而,由于外部的单引号或双引号,EJS渲染后,campground变量实际上被赋值为一个JavaScript字符串字面量,其内容是JSON字符串本身。

例如,如果campground对象是{"geometry":{"type":"Point","coordinates":[8.520355,47.476804]}},那么渲染后的HTML会是:

<script>
    const mapToken = 'TOKEN';
    const campground = '{"geometry":{"type":"Point","coordinates":[8.520355,47.476804]}}'; // 这是一个字符串!
</script>

此时,在showPageMap.js中,campground变量被视为一个普通的字符串,而不是一个JavaScript对象。因此,当尝试访问campground.geometry时,会因为字符串没有geometry属性而返回undefined,进而导致undefined.coordinates的错误。

showPageMap.js:

mapboxgl.accessToken = mapToken;
const map = new mapboxgl.Map({
    container: 'map', // 容器ID
    style: 'mapbox://styles/mapbox/streets-v12', // 样式URL
    center: campground.geometry.coordinates, // 错误发生在这里,因为campground是字符串
    zoom: 8, // 初始缩放级别
});

new mapboxgl.Marker()
    .setLngLat(campground.geometry.coordinates)
    .addTo(map);

解决方案:使用EJS的非转义输出标签

解决这个问题的关键在于正确地将JSON字符串注入到JavaScript代码中,使其能够被JavaScript引擎解析为对象,而不是字符串字面量。EJS提供了两种输出标签:

Molica AI
Molica AI

一款聚合了多种AI工具的一站式创作平台

下载
  • : 转义HTML特殊字符后输出内容。适用于显示文本内容,防止XSS攻击。
  • : 不转义HTML特殊字符直接输出内容。适用于输出HTML片段或JSON字符串等需要保留原始格式的内容。

为了将JSON.stringify(campground)的输出直接作为JavaScript代码的一部分,我们需要使用非转义输出标签

show.ejs (正确示例):

<script>
    const mapToken = '<%=process.env.MAPBOX_TOKEN%>';
    // 正确的做法:直接嵌入JSON字符串,不加外部引号
    const campground = <%- JSON.stringify(campground) %>;
</script>
<div id="map" style="width: 100%; height: 500px;"></div>
<script src="/javascripts/showPageMap.js"></script>

当使用时,EJS会直接将JSON.stringify(campground)的结果(一个有效的JSON字符串)输出到const campground =的后面,而不会额外添加引号。

渲染后的HTML将是:

<script>
    const mapToken = 'TOKEN';
    const campground = {"geometry":{"type":"Point","coordinates":[8.520355,47.476804]}}; // 现在这是一个JavaScript对象!
</script>

此时,campground变量在客户端JavaScript中将是一个真正的JavaScript对象,拥有geometry属性和其内部的coordinates数组。showPageMap.js就可以正确地访问这些属性,Mapbox也能正常初始化。

完整代码示例

show.ejs:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Campground Detail</title>
    <script src='https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.js'></script>
    <link href='https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.css' rel='stylesheet' />
    <!-- 其他CSS/JS引用 -->
</head>
<body>
    <h1><%= campground.title %></h1>
    <p><%= campground.description %></p>
    <div id="map" style="width: 100%; height: 400px;"></div>

    <script>
        // 从环境变量获取Mapbox Token
        const mapToken = '<%=process.env.MAPBOX_TOKEN%>';
        // 正确地将campground对象作为JSON字符串嵌入,并让JS解析为对象
        const campground = <%- JSON.stringify(campground) %>;
    </script>
    <script src="/javascripts/showPageMap.js"></script>
</body>
</html>

showPageMap.js:

// 确保Mapbox GL JS库已加载
if (typeof mapboxgl === 'undefined') {
    console.error('Mapbox GL JS library not loaded.');
} else {
    mapboxgl.accessToken = mapToken; // 使用EJS中定义的mapToken

    const map = new mapboxgl.Map({
        container: 'map', // 地图容器的ID
        style: 'mapbox://styles/mapbox/streets-v12', // Mapbox样式URL
        center: campground.geometry.coordinates, // 使用campground对象的坐标
        zoom: 8 // 初始缩放级别
    });

    // 添加地图导航控件
    map.addControl(new mapboxgl.NavigationControl());

    // 在地图上添加标记
    new mapboxgl.Marker()
        .setLngLat(campground.geometry.coordinates)
        .setPopup(
            new mapboxgl.Popup({ offset: 25 })
                .setHTML(`<h3>${campground.title}</h3><p>${campground.location}</p>`)
        )
        .addTo(map);
}

注意事项与最佳实践

  1. 理解EJS标签的区别: 务必区分和。当需要将服务器端变量作为原始JavaScript、HTML或JSON内容嵌入时,使用。当输出用户输入或其他可能包含恶意HTML的文本时,使用以防止XSS攻击。
  2. 数据安全性: 虽然JSON.stringify()本身会转义字符串中的特殊字符,但当嵌入到HTML中时,如果campground对象中包含可能被解释为HTML标签或脚本的内容(例如,在title或description中),仍需小心。对于显示在HTML元素中的文本,最好始终使用。对于嵌入到JavaScript变量中的JSON,JSON.stringify()通常是安全的。
  3. 变量命名冲突: 确保在EJS模板中定义的JavaScript变量名(如mapToken和campground)在全局作用域或外部JavaScript文件中不会引起冲突。使用const或let进行块级作用域声明可以帮助管理变量作用域。
  4. 错误处理: 在showPageMap.js中,可以添加一些检查,确保campground对象及其属性确实存在,以提高代码的健壮性。例如:if (campground && campground.geometry && campground.geometry.coordinates)。

总结

在EJS模板中集成Mapbox或其他需要JavaScript对象的客户端库时,正确地将服务器端数据序列化并嵌入至关重要。核心在于理解EJS的非转义输出标签,它允许我们将JSON.stringify()生成的JSON字符串直接作为有效的JavaScript对象字面量注入到脚本中,从而避免因类型不匹配导致的“Cannot read properties of undefined”错误。掌握这一技巧,将使您在前后端数据交互中更加游刃有余。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

454

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

546

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

334

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

82

2025.09.10

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

846

2023.08.22

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

562

2023.09.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

760

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

22

2026.03.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

CSS教程
CSS教程

共754课时 | 41.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号