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

Vite留言簿前端无法展示数据库数据,请求技术排查协助

留言簿应用无法展示留言条目排查

我用Vite构建了一个留言簿应用,预期功能是用户提交姓名、日期和评论后,页面展示所有历史留言。现在的问题是:提交表单后数据能成功存入guestbook数据库(Postman测试根路由和POST接口都正常,VS Code里能看到数据库内容),但Chrome浏览器页面加载不出任何留言条目,端口设置为7777。以下是相关代码,求帮忙排查。


HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <script type="module" src="/main.js" defer></script>
  <title>Cold and rainy cottage guest book</title>
</head>
<body>
  <div class="nav-bar">
    <h4>Cold and rainy Cottege guest book!</h4>
    <form id="form">
      <label for="name">Name</label>
      <input id="name" type="text" name="name" />
      <label for="date">Date</label>
      <input type="text" name="date" id="date" />
      <label for="comment">Comment</label>
      <input type="text" id="comment" name="comment" />
      <button type="submit">submit</button>
    </form>
  </div>
  <div id="guest-container"></div>
  <div id="new-container"></div>
</body>
</html>

客户端main.js代码

const form = document.getElementById(`form`);
const guestContainer = document.getElementById(`guest-container`);
const newContainer = document.getElementById("new-container");
// 设置基础URL
const baseURL = `http://localhost:7777`;

// 表单提交事件
form.addEventListener(`submit`, async (e) => {
  e.preventDefault();
  const formData = new FormData(form);
  const entryData = Object.fromEntries(formData);
  const response = await fetch(`${baseURL}/guestbook`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(entryData),
  });
  if (response.ok) {
    displayGuests();
  } else {
    console.error("Failed to add guest entry", response.status);
  }
});

// 获取所有留言
async function fetchGuests() {
  const guests = await fetch(`${baseURL}/guestbook`);
  let result = await guests.json();
  return result;
}

// 展示留言
async function displayGuests() {
  console.log("function workin");
  let guests = await fetchGuests();
  guestContainer.innerHTML = "";
  guests.forEach((guest) => {
    let h3Tag = document.createElement("h3");
    let pTag = document.createElement("p");
    let commentTag = document.createElement("p");
    let delButton = document.createElement("p");
    let infoDiv = document.createElement("div");
    let guestCard = document.createElement("div");
    h3Tag.textContent = guest.name;
    h3Tag.setAttribute(`class`, `guestName`);
    pTag.textContent = guest.date;
    commentTag.textContent = guest.comment;
    delButton.textContent = `X`;

    infoDiv.appendChild(h3Tag);
    infoDiv.appendChild(pTag);
    guestCard.appendChild(infoDiv);
    guestCard.appendChild(commentTag);
    guestCard.appendChild(delButton);
    guestContainer.appendChild(guestCard);
    newContainer.appendChild(guestContainer);

    console.log("function ran :(");
    // 删除按钮事件
    delButton.addEventListener(`click`, (e) => {
      e.preventDefault();
      handleDelete(guest.id);
    });
  });
}

// 删除留言
async function handleDelete(id) {
  const result = await fetch(`${baseURL}/guestbook/${id}`, {
    method: "DELETE",
  });
  console.log(result);
  if (result.ok) {
    displayGuests();
  }
}

// 初始化展示留言
displayGuests();

服务端server.js代码

import express from "express";
import cors from "cors";
import Database from "better-sqlite3";

const app = express();
const PORT = `7777`;
const db = new Database("database.db");

// 中间件
app.use(express.json());
app.use(cors());

// 启动服务
app.listen(`${PORT}`, () => {
  console.log(`port started on PORT:${PORT}`);
});

// 根路由
app.get("/", (req, res) => {
  res.send(`root ROUTE ⊂(◉‿◉)つ`);
});

// 获取留言接口
app.get("/guestbook", (req, res) => {
  try {
    // 根据ID查询单条留言
    if (req.query.id) {
      let guestBook = db
        .prepare(`SELECT * FROM guestbook WHERE id = ?`)
        .all(`req.query.id`);
      res.status(200).json(guestBook);
      return;
    }
  } catch (err) {
    res.status(500).json(err);
  }
  if (req.query.one) {
    res.send("Query one");
  }
});

// 添加留言接口
app.post("/guestbook", (req, res) => {
  try {
    const name = req.body.name;
    const date = req.body.date;
    const comment = req.body.comment;
    const newEntry = db
      .prepare(`INSERT INTO guestbook (name , date , comment) VALUES(?,?, ?)`)
      .run(name, date, comment);
    res.status(200).json(newEntry);
  } catch (err) {
    res.status(500).json({ error: err });
  }
});

// 删除留言接口
app.delete("/guestbook/:id", (req, res) => {
  try {
    const id = req.params.id;
    const deletedEntry = db
      .prepare(`DELETE FROM guestbook WHERE id = ? `)
      .run(id);
    res.status(200).json({ recordDeleted: deletedEntry });
  } catch (err) {
    res.status(500).json({ error: err });
  }
});

Seed.js代码

import Database from "better-sqlite3";
const db = new Database("database.db")

db.exec(`CREATE TABLE  IF NOT EXISTS movies (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    movie TEXT,
    year INTEGER ,
    imgURL TEXT)`)

db.exec(`
INSERT into movies (movie, year, imgURL)
VALUES
('Black Narcissus' , 1947, 'https://posters.movieposterdb.com/07_11/1947/39192/l_39192_20b67beb.jpg'),
('Ran' , 1985 , 'https://posters.movieposterdb.com/23_04/1985/89881/l_ran-movie-poster_0c1ca44d.jpg'),
('Day of Wrath' , 1943, 'https://posters.movieposterdb.com/21_09/1943/36506/l_36506_d9d2b6c8.jpg' )
 `)

问题排查与修复方案

1. GET接口未返回全部留言数据

服务端/guestbook路由仅在携带id查询参数时返回数据,无参数时没有返回逻辑,客户端请求后拿不到任何留言。修复如下:

app.get("/guestbook", (req, res) => {
  try {
    // 根据ID查询单条留言
    if (req.query.id) {
      let guestBook = db
        .prepare(`SELECT * FROM guestbook WHERE id = ?`)
        .all(req.query.id); // 移除引号,传递变量而非字符串
      res.status(200).json(guestBook);
      return;
    }
    // 返回全部留言数据
    const allGuests = db.prepare(`SELECT * FROM guestbook`).all();
    res.status(200).json(allGuests);
  } catch (err) {
    res.status(500).json(err);
  }
});

2. DOM重复挂载导致结构混乱

displayGuests函数中每次循环都执行newContainer.appendChild(guestContainer),会导致容器被重复添加,修改为仅执行一次:

async function displayGuests() {
  console.log("function workin");
  let guests = await fetchGuests();
  guestContainer.innerHTML = "";
  guests.forEach((guest) => {
    // ... 元素创建代码不变
    guestContainer.appendChild(guestCard);
    // 移除循环内的 newContainer.appendChild(guestContainer)
  });
  // 仅执行一次容器挂载
  newContainer.innerHTML = "";
  newContainer.appendChild(guestContainer);
  console.log("function ran :)");
}

3. Seed.js未初始化guestbook表

当前Seed脚本仅创建了movies表,添加guestbook表的创建逻辑:

db.exec(`CREATE TABLE IF NOT EXISTS guestbook (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT,
    date TEXT,
    comment TEXT
)`);

4. 添加客户端请求错误处理

避免请求失败时forEach报错,给fetchGuests添加错误捕获:

async function fetchGuests() {
  try {
    const guests = await fetch(`${baseURL}/guestbook`);
    if (!guests.ok) throw new Error('请求失败');
    let result = await guests.json();
    return result;
  } catch (err) {
    console.error('获取留言失败:', err);
    return [];
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 15:25:54