You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于Node.js+Express构建无框架单页应用的动态页面问题

没问题!我之前帮不少开发者实现过这种纯JS+Express的单页应用,完全不用依赖React、Angular这类框架,咱们一步步来搞定:

1. 后端Express核心配置

首先调整Express的配置,让它既能提供静态资源,又能支持SPA的路由 fallback(所有非API请求都返回index.html,交给前端路由接管)。

先安装依赖:

npm install express

然后编写你的app.js

const express = require('express');
const path = require('path');
const app = express();

// 把前端的HTML/CSS/JS都放在public文件夹,让Express能访问到
app.use(express.static(path.join(__dirname, 'public')));

// 这里放你的API接口(如果需要的话)
app.get('/api/contact-info', (req, res) => {
  res.json({ phone: '123456789', email: 'contact@example.com' });
});

// SPA关键:所有非API的路由都返回index.html,让前端路由处理
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`服务器跑在 http://localhost:${PORT}`);
});
2. 前端页面基础结构

你的index.html(放在public文件夹下)需要有固定的导航栏,和一个用来动态替换内容的容器:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>我的SPA应用</title>
  <style>
    nav { background: #2c3e50; padding: 1rem; }
    nav a { color: white; margin-right: 1.5rem; text-decoration: none; }
    #content { padding: 2rem; max-width: 1000px; margin: 0 auto; }
  </style>
</head>
<body>
  <nav>
    <a href="/">首页</a>
    <a href="/contact">联系我们</a>
    <a href="/about">关于我们</a>
  </nav>
  <!-- 动态内容会替换到这个容器里 -->
  <div id="content"></div>

  <script src="/router.js"></script>
</body>
</html>
3. 前端路由核心逻辑(router.js)

这部分是实现无刷新页面切换的关键,用纯JS监听导航点击、管理历史记录、加载页面片段。创建public/router.js

const contentContainer = document.getElementById('content');

// 路由映射:URL路径对应要加载的HTML片段文件
const routes = {
  '/': '/pages/home.html',
  '/contact': '/pages/contact.html',
  '/about': '/pages/about.html'
};

// 加载页面内容的异步函数
async function loadPage(path) {
  // 可选:显示加载状态
  contentContainer.innerHTML = '<p>加载中...</p>';
  
  try {
    // 请求对应的HTML片段
    const response = await fetch(routes[path] || '/pages/404.html');
    const html = await response.text();
    // 替换内容容器
    contentContainer.innerHTML = html;
    // 更新页面标题
    document.title = path === '/' ? '首页' : `${path.slice(1)}页面`;
  } catch (err) {
    contentContainer.innerHTML = '<h1>页面加载失败了😥</h1>';
    console.error('加载出错:', err);
  }
}

// 处理导航栏点击事件
function handleNavClick(e) {
  if (e.target.tagName === 'A') {
    e.preventDefault(); // 阻止默认的页面跳转
    const path = e.target.getAttribute('href');
    // 更新浏览器历史记录,让前进后退能正常工作
    window.history.pushState({ path }, '', path);
    // 加载对应页面
    loadPage(path);
  }
}

// 监听浏览器前进后退按钮
window.addEventListener('popstate', (e) => {
  const path = e.state?.path || '/';
  loadPage(path);
});

// 页面初始化时加载当前路由对应的内容
document.addEventListener('DOMContentLoaded', () => {
  const initialPath = window.location.pathname;
  loadPage(initialPath);
  // 给导航栏绑定点击事件
  document.querySelector('nav').addEventListener('click', handleNavClick);
});
4. 创建页面片段

在public文件夹下新建pages子文件夹,然后创建对应的HTML片段:

  • public/pages/home.html
<h1>欢迎来到首页</h1>
<p>这是一个用Express+纯JS构建的单页应用,完全没有用React哦!</p>
  • public/pages/contact.html
<h1>联系我们</h1>
<form id="contact-form">
  <div>
    <label>姓名:<input type="text" name="name" required></label>
  </div>
  <div style="margin: 1rem 0;">
    <label>邮箱:<input type="email" name="email" required></label>
  </div>
  <button type="submit">提交留言</button>
</form>
  • public/pages/about.html
<h1>关于我们</h1>
<p>我们致力于用最简单的技术栈构建高效的Web应用。</p>
5. 额外优化小技巧
  • 路由参数支持:如果需要带参数的路由(比如/user/123),可以把routes改成正则匹配,或者手动解析window.location.pathname提取参数。
  • 脚本执行:如果页面片段里有JS代码,innerHTML不会自动执行,你可以在加载完HTML后手动提取脚本标签并执行,或者把逻辑放在router.js里用事件委托处理。
  • 404页面:新增pages/404.html,在路由匹配失败时加载它,提升用户体验。

这样一套下来,你就能实现完全基于Node.js+Express+纯JS的单页应用,不用依赖任何前端框架,就能完成无刷新的页面切换啦!

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

火山引擎 最新活动