在EJS、Express与Node.js中如何通过点击事件传递JSON对象到其他页面
问题根源
你遇到的所有报错都是以下几个明确的代码错误导致的:
- 前端重复定义函数:把
editOrder函数写在循环里,每次循环都会覆盖上一次的同名函数,最终只能拿到最后一条pickup数据,完全匹配不到点击行的对应数据 - 未做JSON类型转换:前端拿到的序列化结果是字符串类型,没有转成JS对象,自然无法读取属性
- URL传参格式错误:查询字符串需要遵循
key=value格式,你直接把JSON字符串拼在?后面,等于把整个JSON当参数键、值为空,这就是服务端打印结果里整个JSON是键的原因 - 服务端未做参数解析:拿到字符串格式的JSON后没有转成对象,自然无法读取属性
修正方案
第一步:修改EJS页面代码
不要循环生成script标签,把当前行的pickup数据直接作为参数传递给点击函数:
<% for(let i=0; i < user.pickups.length; i++){%> <td> <button type="button" name="theButton" class="edit-selected btn btn-ship btn-sm" onclick="editOrder(<%- JSON.stringify(user.pickups[i]) %>)" > Ed </button> </td> <%}%> <!-- 函数只定义一次,放在循环外部 --> <script> function editOrder(pickup) { // 这里pickup已经是JS对象,可以直接读取属性 console.log(pickup._id, pickup.contacts.email) if (pickup) { // 序列化后做URL编码,作为value绑定到orderData参数上 const orderStr = encodeURIComponent(JSON.stringify(pickup)) window.location = '/users/dashboard/orders?orderData=' + orderStr } } </script>
第二步:修改Express路由代码
Express已经自动处理了URL参数解析,不需要手动调用url.parse,拿到参数后解码转成对象即可:
router.get('/users/dashboard/orders', async (req, res) => { try { const orderStr = req.query.orderData const order = JSON.parse(decodeURIComponent(orderStr)) // 现在可以正常读取所有属性 console.log(order._id, order.contacts.email) // 把解析完成的对象传递给新页面渲染 res.render('orders', { order }) } catch (err) { console.log(err) res.status(500).send('参数解析错误') } })
第三步:新页面使用数据
在orders.ejs里可以直接读取order对象的所有属性,比如显示邮箱写<%= order.contacts.email %>即可。
补充优化建议:如果数据量较大、或者对安全性有要求,不建议通过URL传递完整对象,可以只传递订单
_id,服务端收到id后再查询数据库拿到完整数据,既避免URL长度超限,也防止前端篡改数据。
内容的提问来源于stack exchange,提问作者Tamia
相关产品推荐
相关产品推荐

