EJS 未渲染

问题描述 投票:0回答:1

我正在 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;
}
javascript node.js express ejs
1个回答
0
投票

按照您设置代码的方式,它无法显示结果。让我们来看看发生了什么:

  1. 用户在
    /
    打开页面并可以选择其中一张图像
  2. 一旦点击任何图像,比如说剪刀,您就可以向后端的
    POST
    发送一个
    /add
    请求,其中包含数据
    {targetedId: "scissors", dataIdList: ["paper", "rock", "scissors"]}
  3. /add
    的路由处理程序选择一个随机选项,然后检查结果。
  4. 一旦确定结果,数组
    gameResults
    现在将包含结果并重定向到
    /
    进行响应。该路由的路由器处理程序将获取并重置
    gameResults
    的值,因此现在
    gameResults
    又是一个空数组。
  5. 页面将被渲染,渲染的标记将作为响应发送回获取请求。这意味着
    response.text().then(text => console.log(text));
    行应该打印整个页面的HTML标记以及呈现的结果。但由于用户所在的页面没有进行任何操作,因此除了未单击的图像“隐藏”和标记的控制台日志之外,不会发生任何事情。
  6. 如果用户尝试重新加载页面,它仍然不会显示任何结果,因为如果我们记得的话,在
    /
    处理程序中重定向到
    /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 的不同方法,请告诉我:)

© www.soinside.com 2019 - 2024. All rights reserved.