尝试循环 JS 对象时出现“无效字符串长度”错误

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

我对编程非常陌生,现在我正在尝试构建我的第一个应用程序。这是一个日常开支跟踪器。我正在努力解决的部分是:当用户添加新项目(例如咖啡)和金额时,应该创建一个新的 div,其中包含项目和金额。每次用户添加新的项目和数量时,都应该创建一个新的 div。我试图用 for 循环来实现这一点,但是在运行代码时出现“无效的字符串长度”错误。也许还有另一种方法来实现这个逻辑或者我如何修复我的代码?我正在使用 Node JS、Express 和 EJS。

EJS 代码片段:

<div class = "add-new-item">
            <div class = "add-item">
                <form class= "item" action = "/add-new-item" method="post">
                    <input type="text" name="newItem" placeholder="Item" autocomplete="off" autofocus="true" />
                    <input type="text" name="newAmount" placeholder="Amount" autocomplete="off" autofocus="true" />
                    <button type="submit" value="Add" id="addBtn">+</button>            
                </form>                   
            </div>
        </div>   

        <%if (locals.item && locals.amount) {%>
            <%let items = [];%>
            <%items.push({item, amount});%>
            <%console.log(items);%>

            <%for(let i = 0; i = Object.keys(items).length; i++) {%>
                <div class = "new-item">
                    <div class = "item">
                        <%= item %>
                    </div>
            
                    <div class = "amount">
                        €<%= amount %> 
                    </div>
                </div>%>
            <%}%>
            <% };%>

JS代码片段:

import express from "express";
import bodyParser from "body-parser";

const app = express();
const port = 3000;

app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));



app.get("/", (req, res) => {
    res.render("index.ejs");
});

app.post("/add-new-item", async (req, res) => {
  const item = req.body.newItem;
  const amount = req.body.newAmount; 
  
  res.render("index.ejs", {item: item, amount: amount});
  
});


app.listen(port, () => {
  console.log(`API is running at http://localhost:${port}`);
});
javascript node.js express ejs
1个回答
0
投票

发生这种情况很可能是因为 for 循环中的

i = Object.keys(items).length
。 for 循环的语法是(MDN 文档):

for (initialization; condition; afterthought)
  statement

所以第二个参数是一个条件,要求一个布尔值。但相反,您给它分配了变量

i
,因此作为一个条件,它会检查您分配给
i
的值,并且
Object.keys(items).length
将始终导致
true
。不仅如此,它还为每个循环分配长度给
i
。这是一个关于您正在做什么的小示例(这是一个 demo,因为您甚至无法在大多数网络环境中运行它):

let a = [1, 2, 3, 4, 5];
for(let i = 0; i = a.length; i++) {
  console.log(i);
}

这样,你也形成了一个无限循环,唯一阻止它的是“无效的字符串长度”错误。

要修复循环,您需要将其更改为:

<%for(let i = 0; i < items.length; i++) {%>
// or
<%for(let i = 0; i <= items.length - 1; i++) {%>

但是整个代码逻辑似乎并没有达到预期目的,因为每次

items
数组中都只有 1 个对象。

从我在你的代码中看到的内容来看,它是这样的:

  • 在路线“/”上获取,这将渲染index.ejs
  • 用户在表单中添加一个项目,该项目将发布到“/add-new-item”
  • “/add-new-item”路由的处理程序然后再次呈现index.ejs,但将对象作为包含 1 个项目和 1 个金额变量的数据传递
  • ejs 渲染模板,因此它创建空的
    items
    数组并推送该对象

但最终,这意味着这些项目永远不会存储在任何地方,如果我们要在上面列表中执行的操作之后添加新项目,则整个过程将重复。所以最后,它只会替换其他项目,并且始终只存在一个项目。

相反,您应该做的是,当用户添加项目时,向服务器发送 fetch 请求。然后,服务器上的处理程序将项目和金额添加到服务器上存储的数组或数据库中。随后,您可以将包含所有项目的数组发送回 fetch API,让 ejs 使用新值再次渲染 for 循环内的部分并将其插入到 DOM(需要客户端上的 ejs),或者在服务器并将其发回。然后,您可以修改呈现index.ejs的路由处理程序,这样您就可以始终将项目数组(要么已经存在于服务器上,要么总是在发送之前从数据库获取)作为数据传递。如果它为空,则 for 循环内不会渲染任何内容,如果它有值,则将渲染这些值。

一般来说,您很少在 ejs 标签中定义变量,如果您这样做,它们很可能是小的路由相关变量,例如页面标题。我希望这对您有帮助,如果您需要帮助,请随时询问更多:)

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