You need to enable JavaScript to run this app. 如何将EJS数据干净地传递给JavaScript变量?
优惠活动
大模型
产品
解决方案
定价
更多

如何将EJS数据干净地传递给JavaScript变量?

最干净的实现方案

用HTML原生自定义数据属性(data-*)绑定数据

这是HTML标准定义的、专门用于元素存储自定义交互数据的原生能力,根本不需要额外加隐藏的DOM节点,数据和触发交互的按钮直接强绑定,完全不用写DOM遍历、找父级子级的杂乱逻辑。
只需要修改现有EJS代码里的加购按钮,把需要的产品数据直接作为标准属性挂在按钮上:

<div class="productSection">
  <% products.forEach(function(product){ %>                         
    <div class="card">
      <div class="card-title"><%- product.name %></div>
      <div class="card-body">
        <div class="card-body-price"><%- product.price %></div>
      </div>
      <!-- 直接把产品核心数据绑定到加购按钮上 -->
      <button 
        class="card-cartBtn"
        data-product-id="<%= product._id %>"
      >+</button>
    </div>              
  <% }) %>
</div>

对应的JS逻辑不用给每个按钮单独绑事件,直接用事件委托监听整个产品区域的点击,靠原生的datasetAPI直接从点击的按钮上读数据就行:

document.querySelector('.productSection').addEventListener('click', (e) => {
  // 只处理加购按钮的点击
  if (e.target.classList.contains('card-cartBtn')) {
    // 直接拿按钮上存的product._id,完全不用爬DOM层级
    const productId = e.target.dataset.productId
    // 直接传值给购物车逻辑就行
    addToCart(productId)
  }
})

这种方式的好处非常直接:

  • 没有任何多余的隐藏DOM,交互数据和触发交互的元素一一对应,逻辑扫一眼就懂,不会出现找半天数据藏在哪个父节点的情况
  • 原生API取值,后续哪怕调整DOM结构(比如给按钮加几层包裹元素),取值逻辑也不会轻易失效
  • 用事件委托的模式,哪怕后续动态加载新的产品卡片,也不需要给新按钮重新绑事件,性能更好
  • 输出属性值用<%= %>做HTML转义,能避免特殊字符截断属性、引发XSS的风险

如果需要传递的产品字段很多,把所有字段都堆在data-*属性上会让DOM代码臃肿,就换个更清爽的方式:把服务端拿到的产品数据整体序列化成合法JSON,直接注入到页面的JS全局作用域里:

<script>
  // 序列化产品数据存入全局变量,转义尖括号防止XSS
  window.PRODUCTS = <%- JSON.stringify(products.map(p => ({
    id: p._id,
    name: p.name,
    price: p.price
  })).replace(/<\//g, '<\\/') %>
</script>

这种情况下按钮上只需要存一个核心的product id,点击时直接从全局数组里匹配对应的完整产品数据就行,不用把全量字段都铺在DOM上。

要明确一点:标准的data-*自定义属性是浏览器原生支持的规范能力,和你反感的"写display:none的隐藏div存数据"的野路子完全不是一回事,是业内通用的干净实现,不存在杂乱的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.05 13:27:00