我正在 Node.js 后端使用 Express 服务器、frontend.js 客户端、index.ejs 和 main.css 文件制作石头、剪刀、布游戏。我首先想渲染你的决定结果的字符串行(赢了,输了,相同 - 再试一次)。 但是,它不会呈现结果。我尝试使用
console.log
来检测数据是否在路由之间传递,这确实发生了,它从字面上显示数据位于 ejs 模板中,但它仍然没有渲染。
我尝试使用聊天 GPT 来解决这个问题,但失败了......
后端.js:
import express from "express";
import bodyParser from "body-parser";
import pg from "pg";
import ejs from "ejs";
import axios from "axios";
import { dirname } from "path";
import { fileURLToPath } from "url";
// import icons from "bootstrap-icons";
const __dirname = dirname(fileURLToPath(import.meta.url));
const app = express();
const port = 3000;
let gameResult = [];
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));
app.get("/", (req, res) => {
const results = [...gameResult];
gameResult = [];
console.log("Result from session:", results);
res.render("index", {results});
});
app.post("/add", (req,res) => {
const {targetedId, dataIdList} = req.body;
let compSelector = dataIdList[Math.floor(Math.random() * dataIdList.length)];
console.log(`Chosen by client: ${targetedId}`);
console.log(`Chosen by computer: ${compSelector}`);
function determineResult(targetedId, compSelector) {
switch (targetedId) {
case "paper":
if(compSelector === "scissors") {
return "You lost";
} else if(compSelector === "rock") {
return "You won!";
} else {
return "The same, try again";
}
break;
case "scissors":
if(compSelector === "rock") {
return "You lost";
} else if(compSelector === "paper") {
return "You won!"
} else {
return "The same, try again";
}
break;
case "rock":
if(compSelector === "paper") {
return "You lost";
} else if(compSelector === "scissors") {
return "You won!"
} else {
return "The same, try again";
}
break;
default:
console.log("Error");
break;
}
}
try {
const result = determineResult(targetedId, compSelector);
console.log(result);
gameResult = [result];
res.redirect("/");
} catch (error) {
console.error("Error handling POST /add request:", error);
res.status(500).send("Internal Server Error");
}
});
app.listen(port, () => {
console.log(`Listening on port ${port}`);
});
前端.js:
console.log("Frontend.js is loaded");
function myFrontFunction(event) {
const selectedImage = event.target;
const targetedId = selectedImage.getAttribute("data-id");
const images = document.querySelectorAll(".image");
const dataIdList = [];
images.forEach(dataId => {
dataIdList.push(dataId.getAttribute("data-id"));
});
console.log(`Data list: ${dataIdList}`);
// console.log(typeof(idData));
console.log(targetedId);
fetch("/add", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({targetedId, dataIdList}),
})
.then(response => {
if(response.ok) {
console.log("Data sent successfully");
response.text().then(text => console.log(text));
console.log("All images:", images);
images.forEach(image => {
if(image !== selectedImage){
console.log("Hiding image:", image);
image.classList.add('hidden'); // Use class to hide
}
});
} else {
console.error("Failed to send data to the server");
}
})
.catch(error => console.error("Error:", error));
}
index.ejs:
<%- include('partials/header.ejs') %>
<h1>The RSP App!</h1>
<h2>Choose Rock, Scissors or Paper:</h2>
<img class="image" src="/images/paper.png" alt="A piece of paper" width="400px" height="400px" data-id="paper" onclick="myFrontFunction(event)">
<img class="image" src="/images/rock.png" alt="A rock" width="400px" height="400px" data-id="rock" onclick="myFrontFunction(event)">
<img class="image" src="/images/scissors.png" alt="Scissors" width="400px" height="400px" data-id="scissors" onclick="myFrontFunction(event)">
<div>
<% if (results.length > 0) { %>
<% results.forEach( result => { %>
<p> <%= result %></p>
<% }) %>
<% } %>
</div>
<script src="/frontend.js"></script>
<%- include('partials/footer.ejs') %>
main.css:
.hidden {
display: none;
}
按照您设置代码的方式,它无法显示结果。让我们来看看发生了什么:
/
打开页面并可以选择其中一张图像POST
发送一个 /add
请求,其中包含数据 {targetedId: "scissors", dataIdList: ["paper", "rock", "scissors"]}
/add
的路由处理程序选择一个随机选项,然后检查结果。gameResults
现在将包含结果并重定向到 /
进行响应。该路由的路由器处理程序将获取并重置 gameResults
的值,因此现在 gameResults
又是一个空数组。response.text().then(text => console.log(text));
行应该打印整个页面的HTML标记以及呈现的结果。但由于用户所在的页面没有进行任何操作,因此除了未单击的图像“隐藏”和标记的控制台日志之外,不会发生任何事情。/
处理程序中重定向到 /add
已将 gameResults
的值重置为 []
所以基本上你最终所做的就是“忽略”随提取请求返回的结果,同时丢弃后端的值。
因此,为了使当前代码正常工作,您可以做的就是将结果本身作为响应发送回来,并将其添加到页面的新元素中,例如:
后端.js
try {
const result = determineResult(targetedId, compSelector);
res.send(result);
} catch (error) {
...
}
前端.js
fetch(...)
.then(res => res.text())
.then(text => {
let p = document.createElement('p');
p.textContent = text;
document.querySelector('div').appendChild(p);
});
还有很多其他方法可以做到,这取决于你想怎么做。如果您查看@KooiInc 在评论中链接的内容,您可以看到一种完全适用于客户端的方法。对于初学者来说,这可能看起来有点吓人,我建议用一些换行符分隔行,以便更好地概览,然后了解发生了什么。
即使您想使用后端计算和 EJS 来实现,也有不同的方法来实现这一点,但正如我所说,最终取决于您想要如何实现。如果您想了解后端+EJS 的不同方法,请告诉我:)