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

如何在页面加载后/事件触发时调用Express变量,避免提前执行?

办公室地图弹窗显示工位用户信息解决方案

问题核心

当前实现是通过页面跳转获取工位用户信息,但需求是在原页面弹窗展示。之前尝试在EJS中嵌入局部模板时报错,原因是EJS是服务器端渲染模板,页面加载时会立即解析所有EJS标签,而初始加载首页时没有传递user参数,导致users.ejs中user变量未定义。


可行方案

方案1:前端异步请求(Fetch)+ 动态渲染弹窗

适合工位数量较多的场景,点击工位时通过API请求获取数据,再动态填充弹窗内容,无需页面跳转。

1. 修改app.js,新增API接口返回JSON数据

保留原有页面路由(若需保留跳转功能),新增专门返回用户数据的API:

// 新增API接口,返回指定工位的用户JSON
app.get("/api/user/:place", async (req,res) => {
  try {
    const place = req.params.place;
    const user = await getUser(place);
    res.json(user);
  } catch (err) {
    res.status(500).json({error: '获取用户信息失败'});
  }
});

// 首页路由,仅渲染index.ejs,无需传递user参数
app.get("/", (req,res) => {
  res.render('index.ejs');
});

2. 修改index.ejs,添加弹窗容器与点击事件

移除area标签的href,改用点击事件触发请求,动态渲染弹窗:

<!-- 隐藏的弹窗容器 -->
<div id="userPopup" style="display:none; position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); padding:20px; background:#fff; border:1px solid #ddd; border-radius:8px; z-index:1000;">
  <div class="popup_title">
    <h2>姓名: <span id="userName"></span></h2>
  </div>
  <div class="popup_text">
    <p>工位: <span id="userPlace"></span></p>
    <!-- 可添加更多用户信息字段,如邮箱、部门等 -->
  </div>
  <button style="margin-top:15px; padding:8px 16px;" onclick="closePopup()">关闭</button>
</div>

<!-- 修改area标签,绑定点击事件 -->
<area onclick="showUserInfo('6А1')" coords="1048,515,1001,560" shape="rect">

<script>
function showUserInfo(place) {
  // 发送异步请求获取用户数据
  fetch(`/api/user/${place}`)
    .then(res => res.json())
    .then(user => {
      // 填充弹窗内容
      document.getElementById('userName').textContent = user.name;
      document.getElementById('userPlace').textContent = user.place;
      // 显示弹窗
      document.getElementById('userPopup').style.display = 'block';
    })
    .catch(err => {
      console.error('请求错误:', err);
      alert('获取用户信息失败');
    });
}

function closePopup() {
  document.getElementById('userPopup').style.display = 'none';
}
</script>

方案2:服务器预加载所有工位数据(适合小数据量场景)

如果办公室工位数量较少,可在首页加载时一次性获取所有用户数据,点击工位时直接从本地数据中匹配,无需每次请求服务器。

1. 修改database.js,新增获取所有用户的函数

export async function getAllUsers() {
  const [rows] = await pool.query(`SELECT * FROM users`);
  return rows;
}

2. 修改app.js,首页传递所有用户数据

app.get("/", async (req,res) => {
  try {
    const allUsers = await getAllUsers();
    // 将数据转为JSON字符串传递给前端
    res.render('index.ejs', { allUsers: JSON.stringify(allUsers) });
  } catch (err) {
    res.status(500).send('页面加载失败');
  }
});

3. 修改index.ejs,本地匹配数据渲染弹窗

<div id="userPopup" style="display:none; position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); padding:20px; background:#fff; border:1px solid #ddd; border-radius:8px; z-index:1000;">
  <div class="popup_title">
    <h2>姓名: <span id="userName"></span></h2>
  </div>
  <div class="popup_text">
    <p>工位: <span id="userPlace"></span></p>
  </div>
  <button style="margin-top:15px; padding:8px 16px;" onclick="closePopup()">关闭</button>
</div>

<area onclick="showUserInfo('6А1')" coords="1048,515,1001,560" shape="rect">

<script>
// 将服务器传递的JSON转为JS对象
const allUsers = JSON.parse('<%= allUsers %>');

function showUserInfo(place) {
  // 匹配对应工位的用户
  const user = allUsers.find(u => u.place === place);
  if (user) {
    document.getElementById('userName').textContent = user.name;
    document.getElementById('userPlace').textContent = user.place;
    document.getElementById('userPopup').style.display = 'block';
  } else {
    alert('该工位暂无用户信息');
  }
}

function closePopup() {
  document.getElementById('userPopup').style.display = 'none';
}
</script>

关键说明

  • 之前的错误根源:EJS模板在服务器端解析完成后才会发送到前端,前端JS函数中无法再执行EJS标签,因此不能把include('users.ejs')放在前端点击函数里。
  • 方案选择:工位数量多选方案1(减少初始加载压力),数量少选方案2(提升交互速度)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 09:40:40