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

Node.js CRUD应用中如何实现无刷新跨页面数据传递?

问题:Node.js CRUD应用无法无刷新传递数据

我基于Node.js、Express、Handlebars和MySQL开发的CRUD应用功能正常,但尝试在不刷新目标页面的情况下传递数据时完全没效果,已经卡了3天。以下是相关代码:

主页代码(Handlebars+HTML)

{{#if removedUser}}
<div class="alert alert-success alert-dismissible fade show" role="alert">
  User has been removed.
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{{/if}}

<div class="row">
  <div class="col-6">
    <h1>Users</h1>
  </div>
  <div class="col-6 d-flex justify-content-end">
    <a href="/adduser" type="button" class="btn btn-primary align-self-center">+ add user</a>
  </div>
</div>

<table class="table table-bordered">
  <thead class="thead-dark">
    <tr>
      <th scope="col">#</th>
      <th scope="col">First Name</th>
      <th scope="col">Last Name</th>
      <th scope="col">Email</th>
      <th scope="col">Credits</th>
      <th scope="col" class="text-end">Action</th>
    </tr>
  </thead>
  <tbody>

    {{#each rows}}
    <tr>
      <th scope="row">{{this.id}}</th>
      <td>{{this.first_name}}</td>
      <td>{{this.last_name}}</td>
      <td>{{this.email}}</td>
      <td>{{this.credits}}</td>
      <td class="text-end">
        <div class="input-group input-group-sm mb-3">
          <form action="/credits/{{this.id}}" method="post">
            <input type="number" class="form-control" placeholder="Credits" name="input_credits" id="input_credits"
              aria-label="Sizing example input" aria-describedby="inputGroup-sizing-sm">
            <div class="col-12 d-grid">
              <!-- 修复input与button标签嵌套错误 -->
              <button class="bi bi-plus" id="post_comment" type="submit">Add</button>
            </div>
          </form>
        </div>
        <a href="/viewuser/{{this.id}}" type="button" class="btn btn-light btn-small"><i class="bi bi-eye"></i> View</a>
        <a href="/edituser/{{this.id}}" type="button" class="btn btn-light btn-small"><i class="bi bi-pencil"></i>
          Edit</a>
      </td>
    </tr>
    {{/each}}

    <!-- 修正{{this.credits}}无法取值问题,添加用户ID参数 -->
    <a href="/label?userId=4" type="button" class="btn btn-primary align-self-center">View Credits Label</a>

  </tbody>
</table>

<!-- 修复未闭合的script标签 -->
<script src="/javascripts/jquery-1.6.4.min.js"></script>
<script src="/javascripts/script.js"></script>

目标页面(label页面)代码

<div class="row">
    <span class="label label-default" id="set_input" name="set_input">Loading...</span>
</div>

<!-- 修复路径与标签未闭合问题 -->
<script src="/javascripts/jquery-1.6.4.min.js"></script>
<script src="/javascripts/script.js"></script>

CRUD操作代码(Node.js)

const mysql = require('mysql');

// Connection Pool
let connection = mysql.createConnection({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME
});

// View Users
exports.view = (req, res) => {
  connection.query('SELECT * FROM user WHERE status = "active"', (err, rows) => {
    if (!err) {
      let removedUser = req.query.removed;
      res.render('home', { rows, removedUser });
    } else {
      console.log(err);
    }
    console.log('The data from user table: ', rows);
  });
}

// Find User by Search
exports.find = (req, res) => {
  let searchTerm = req.body.search;
  connection.query('SELECT * FROM user WHERE first_name LIKE ? OR last_name LIKE ?', ['%' + searchTerm + '%', '%' + searchTerm + '%'], (err, rows) => {
    if (!err) {
      res.render('home', { rows });
    } else {
      console.log(err);
    }
    console.log('The data from user table: ', rows);
  });
}

exports.form = (req, res) => {
  res.render('add-user');
}

// Add new user
exports.create = (req, res) => {
  const { first_name, last_name, email, credits, comments } = req.body;
  connection.query('INSERT INTO user SET first_name = ?, last_name = ?, email = ?, credits = ?, comments = ?', [first_name, last_name, email, credits, comments], (err, rows) => {
    if (!err) {
      res.render('add-user', { alert: 'User added successfully.' });
    } else {
      console.log(err);
    }
    console.log('The data from user table: ', rows);
  });
}

// Edit user
exports.edit = (req, res) => {
  connection.query('SELECT * FROM user WHERE id = ?', [req.params.id], (err, rows) => {
    if (!err) {
      res.render('edit-user', { rows });
    } else {
      console.log(err);
    }
    console.log('The data from user table: ', rows);
  });
}

// Update User
exports.update = (req, res) => {
  const { first_name, last_name, email, credits, comments } = req.body;
  connection.query('UPDATE user SET first_name = ?, last_name = ?, email = ?, credits = ?, comments = ? WHERE id = ?', [first_name, last_name, email, credits, comments, req.params.id], (err, rows) => {
    if (!err) {
      connection.query('SELECT * FROM user WHERE id = ?', [req.params.id], (err, rows) => {
        if (!err) {
          res.render('edit-user', { rows, alert: `${first_name} has been updated.` });
        } else {
          console.log(err);
        }
        console.log('The data from user table: ', rows);
      });
    } else {
      console.log(err);
    }
    console.log('The data from user table: ', rows);
  });
}

// Delete User
exports.delete = (req, res) => {
  connection.query('DELETE FROM user WHERE id = ?', [req.params.id], (err, rows) => {
    if(!err) {
      let removedUser = encodeURIComponent('User succesefully removed');
      res.redirect('/?removed=' + removedUser);
    } else {
      console.log(err);
    }
    console.log('The data from user table: ', rows);
  });
}

// View Users
exports.viewall = (req, res) => {
  connection.query('SELECT * FROM user WHERE id = ?', [req.params.id], (err, rows) => {
    if (!err) {
      res.render('view-user', { rows });
    } else {
      console.log(err);
    }
    console.log('The data from user table: ', rows);
  });
}

// 新增:获取用户积分的API接口
exports.getCredits = (req, res) => {
  connection.query('SELECT credits FROM user WHERE id = ?', [req.params.id], (err, rows) => {
    if (!err) {
      res.json({ success: true, credits: rows[0].credits });
    } else {
      console.log(err);
      res.json({ success: false, error: err.message });
    }
  });
}

// 修改:更新积分后返回JSON,支持无刷新操作
exports.credits = (req, res) => {
  const credits = req.body.input_credits * 100;
  connection.query('UPDATE user SET credits = ? WHERE id = ?', [credits, req.params.id], (err, result) => {
    if (!err) {
      connection.query('SELECT credits FROM user WHERE id = ?', [req.params.id], (err, rows) => {
        if (!err) {
          res.json({ success: true, credits: rows[0].credits });
        } else {
          console.log(err);
          res.json({ success: false, error: err.message });
        }
      });
    } else {
      console.log(err);
      res.json({ success: false, error: err.message });
    }
  });
}

解决思路与实现

当前代码依赖服务端渲染和页面重定向,要实现无刷新传数据,必须用AJAX异步请求+前端DOM更新方案,步骤如下:

1. 注册新增的API路由

在Express主文件中添加:

const crud = require('./path/to/your/crud/file');
// 新增获取积分的API
app.get('/api/credits/:id', crud.getCredits);
// 保留原更新路由,现在返回JSON
app.post('/credits/:id', crud.credits);

2. 前端AJAX提交表单(主页script.js)

// 监听积分更新表单的提交事件
$('form[action^="/credits/"]').submit(function(e) {
  e.preventDefault(); // 阻止默认刷新提交
  const $form = $(this);
  const userId = $form.attr('action').split('/')[2];
  const inputVal = $form.find('input[name="input_credits"]').val();

  if (!inputVal || isNaN(inputVal)) {
    alert('请输入有效的数字');
    return;
  }

  $.ajax({
    url: $form.attr('action'),
    method: 'POST',
    data: { input_credits: inputVal },
    dataType: 'json',
    success: function(res) {
      if (res.success) {
        // 更新当前页面的积分显示
        $form.closest('tr').find('td:eq(4)').text(res.credits);
        // 存储到本地存储,供目标页面监听
        localStorage.setItem(`user_${userId}_credits`, res.credits);
        alert('积分更新成功');
      } else {
        alert('更新失败:' + res.error);
      }
    },
    error: function() {
      alert('服务器错误,请稍后重试');
    }
  });
});

3. 目标页面无刷新获取数据(script.js)

$(document).ready(function() {
  // 从URL参数获取目标用户ID
  const urlParams = new URLSearchParams(window.location.search);
  const targetUserId = urlParams.get('userId') || 4; // 默认ID为4

  // 加载积分数据
  function loadUserCredits() {
    $.ajax({
      url: `/api/credits/${targetUserId}`,
      method: 'GET',
      dataType: 'json',
      success: function(res) {
        if (res.success) {
          $('#set_input').text(res.credits);
        } else {
          $('#set_input').text('加载失败');
        }
      },
      error: function() {
        $('#set_input').text('服务器连接失败');
      }
    });
  }

  // 页面初始化加载
  loadUserCredits();

  // 每隔5秒自动刷新(可选)
  setInterval(loadUserCredits, 5000);

  // 监听本地存储变化,实时更新
  window.addEventListener('storage', function(e) {
    if (e.key === `user_${targetUserId}_credits`) {
      $('#set_input').text(e.newValue);
    }
  });
});

4. 其他代码修正

  • 修复了主页表单按钮的标签嵌套错误
  • 修正了脚本标签未闭合问题
  • 调整了Label按钮链接,添加用户ID参数
  • 删除了原label路由中无效的服务端DOM操作代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 03:55:16