简体   繁体   English

遍历json数组列表

[英]Loop through json array list

We just started 3. semester two weeks ago and are learning basic event/Dom/fetch manipulation. 我们两周前才刚开始学三个学期,正在学习基本的事件/ Dom /提取操作。

I am supposed to fetch data from https://jsonplaceholder.typicode.com/users and get all names and phone numbers. 我应该从https://jsonplaceholder.typicode.com/users获取数据并获取所有名称和电话号码。

So here is what I did: 所以这就是我所做的:

 /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ var userID = document.getElementById("userID"); const url1 = "https://jsonplaceholder.typicode.com/users/"; const url2 = "https://jsonplaceholder.typicode.com/users"; //JSON.stringify(data) function getUser() { fetch(url1 + userID.value) .then(res => res.json()) .then(data => { var all = "<p>" + "Name: " + data.name + "</p>"; all += "<p>" + "Phone: " + data.phone + "</p>"; document.getElementById("singleUser").innerHTML = all; }); } //***************Code that needs look on is right here ******************** function getAllUsers() { fetch(url2) .then(res => res.json()) .then(data => { for (var i = 0; i < data.length; i++) { console.log(data[i]); var all = "<p>" + "Name: " + data[i].name + "</p>"; all += "<p>" + "Phone: " + data[i].phone + "</p>"; document.getElementById("allUsers").innerHTML = all; } //for (var key in data) { // if(data.hasOwnProperty(key)) { // document.getElementById("allUsers").innerHTML = data[key].name; // } //} data.forEach(function(key) { var users = "<p>" + "Name: " + key.name + "</p>"; users += "<p>" + "Phone: " + key.phone + "</p>"; document.getElementById("allUsers").innerHTML = users; console.log(key.name); }); }); } 
 <h1>Hello World!</h1> <h1>Test if deployed on Tomcat via Travis Ci</h1> <h6>Calculator Client</h6> <input type="number" id="firstNumber"><br> <input type="number" id="secondNumber"><br> <div id="operations"> <button name="opr">+</button> <button name="opr">-</button> <button name="opr">X</button> <button name="opr">/</button> <br> </div> <button id="clear">Clear</button> <p id="result"></p> <h6>Dynamic UI manipulation with data obtained via fetch</h6> <input type="number" id="userID"> <button onClick="getUser()">Get user</button> <button onClick="getAllUsers()">Get all</button> <br> <div id="singleUser"></div> <div id="allUsers"></div> <script src="calculator.js" type="text/javascript"></script> <script src="fetch.js" type="text/javascript"></script> 

As you can see I managed to get the single users, which wasn't a problem, but trying to get multiple data rows seems to be a hassle to me. 如您所见,我设法吸引了单个用户,这不是问题,但是尝试获取多个数据行对我来说似乎很麻烦。 I tried 3 different ways all of them keep only giving me the last person in the array, though if I print it to the console it gives me all of it. 我尝试了3种不同的方法,所有这些方法始终只给我阵列中的最后一个人,尽管如果我将其打印到控制台,它也会给我全部。

Please help me. 请帮我。

You need to initialize your result string outside the loop and set the value of the HTML after the loop is finished. 您需要在循环外初始化结果字符串,并在循环结束后设置HTML的值。

 /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ var userID = document.getElementById("userID"); const url1 = "https://jsonplaceholder.typicode.com/users/"; const url2 = "https://jsonplaceholder.typicode.com/users"; //JSON.stringify(data) function getUser() { fetch(url1 + userID.value) .then(res => res.json()) .then(data => { var all = "<p>" + "Name: " + data.name + "</p>"; all += "<p>" + "Phone: " + data.phone + "</p>"; document.getElementById("singleUser").innerHTML = all; }); } //***************Code that needs look on is right here ******************** function getAllUsers() { fetch(url2) .then(res => res.json()) .then(data => { // Traditional for loop var all = ""; for (var i = 0; i < data.length; i++) { //console.log(data[i]); all += "<p>" + "Name: " + data[i].name + "</p>"; all += "<p>" + "Phone: " + data[i].phone + "</p>"; } document.getElementById("allUsers").innerHTML = all; // Enhanced for loop var users = ""; data.forEach(function(key) { users += "<p>" + "Name: " + key.name + "</p>"; users += "<p>" + "Phone: " + key.phone + "</p>"; }); document.getElementById("allUsers").innerHTML = users; // Mapped to string document.getElementById("allUsers").innerHTML = users.map(user => { return "<p>" + "Name: " + user.name + "</p>" + "<p>" + "Phone: " + user.phone + "</p>"; }).join(""); }); } 
 <h1>Hello World!</h1> <h1>Test if deployed on Tomcat via Travis Ci</h1> <h6>Calculator Client</h6> <input type="number" id="firstNumber"><br> <input type="number" id="secondNumber"><br> <div id="operations"> <button name="opr">+</button> <button name="opr">-</button> <button name="opr">X</button> <button name="opr">/</button> <br> </div> <button id="clear">Clear</button> <p id="result"></p> <h6>Dynamic UI manipulation with data obtained via fetch</h6> <input type="number" id="userID"> <button onClick="getUser()">Get user</button> <button onClick="getAllUsers()">Get all</button> <br> <div id="singleUser"></div> <div id="allUsers"></div> <script src="calculator.js" type="text/javascript"></script> <script src="fetch.js" type="text/javascript"></script> 

All your problem are here (normally): document.getElementById("allUsers").innerHTML = all; 您的所有问题都在这里(通常)在这里: document.getElementById("allUsers").innerHTML = all;

The line document.getElementById("allUsers").innerHTML allow you to directly have access to the string content of the DOM element. document.getElementById("allUsers").innerHTML允许您直接访问DOM元素的字符串内容。 In your case you need to append multiple row to this DOM, so you just need to replace the affectation to a append affectation. 在您的情况下,您需要在此DOM上追加多行,因此只需将影响替换为附加影响。 Simply change = to += . 只需将=更改为+=

Here are the modification you need to do: 这是您需要做的修改:

for (var i = 0; i < data.length; i++) {                   
    console.log(data[i]);
    var all = "<p>" + "Name: " + data[i].name + "</p>";
    all += "<p>" + "Phone: " + data[i].phone + "</p>";
    document.getElementById("allUsers").innerHTML += all;
} 

You can also do a more elegent solution: 您还可以做一个更精致的解决方案:

let html = "";

for (let i = 0; i < data.length; i++) {                   
    console.log(data[i]);

    html += "<p>" + "Name: " + data[i].name + "</p>";
    html += "<p>" + "Phone: " + data[i].phone + "</p>";
}

document.getElementById("allUsers").innerHTML = html;

I don't have tested the code, but it should work! 我没有测试代码,但是应该可以!

Just for your knowledge, you should also learn where to use var and let : 仅出于您的知识,您还应该学习在哪里使用varlet

  • var should be used for global variables because they can be reached from anywhere with window.hello (if you variable has "hello" has name). var应该用于全局变量,因为可以通过window.hello从任何地方访问它们(如果变量的名称为“ hello”)。
  • let should be used for local variables because they only can be reached in the same scope. let应该用于局部变量,因为只能在相同范围内访问它们。

It's a simple logic error, related to how you output the data. 这是一个简单的逻辑错误,与如何输出数据有关。 You have put: 您已输入:

document.getElementById("allUsers").innerHTML = users;

within your loop. 在你的循环中。 This means that every time your loop runs, it sets the value of "allUsers" to the users string, which replaces anything which was in that space previously. 这意味着,每次循环运行时,都会将“ allUsers”的值设置为users字符串,该字符串将替换之前在该空间中的任何内容。 Additionally, each time your loop runs, you also reset the users string and only include the user fetched from the current loop iteration into it. 此外,每次循环运行时,也会重置users字符串,并且只包括从当前循环迭代中获取的用户。 By doing both these things you discard all the previous data. 通过执行这两项操作,您将丢弃所有先前的数据。 This happens fast enough that all you actually see on screen is the last one (even though, technically, all the others were displayed for a nanosecond before being over-written!). 这发生得足够快,以至于您实际在屏幕上看到的只是最后一个(即使从技术上讲,所有其他显示都被覆盖了纳秒,然后才被覆盖!)。

You just need to make sure users persists for the whole lifetime of the loop (and that you append to it rather than over-writing it), and that you don't try to put that data into your <div> until you've collected all of it. 您只需要确保users在循环的整个生命周期中都users持久存在(并且将其追加到循环中而不是覆盖它),并且除非您已将数据放入<div> ,否则不要尝试将其放入。收集了所有的东西。

Here's a fixed version: 这是固定版本:

 /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ var userID = document.getElementById("userID"); const url1 = "https://jsonplaceholder.typicode.com/users/"; const url2 = "https://jsonplaceholder.typicode.com/users"; //JSON.stringify(data) function getUser() { fetch(url1 + userID.value) .then(res => res.json()) .then(data => { var all = "<p>" + "Name: " + data.name + "</p>"; all += "<p>" + "Phone: " + data.phone + "</p>"; document.getElementById("singleUser").innerHTML = all; }); } //***************Code that needs look on is right here ******************** function getAllUsers() { fetch(url2) .then(res => res.json()) .then(data => { var users = ""; //declare empty string data.forEach(function(key) { //append to the string users += "<p>" + "Name: " + key.name + "</p>"; users += "<p>" + "Phone: " + key.phone + "</p>"; console.log(key.name); }); //wait until the string contains everyone before we add it to the page! document.getElementById("allUsers").innerHTML = users; }); } 
 <h1>Hello World!</h1> <h1>Test if deployed on Tomcat via Travis Ci</h1> <h6>Calculator Client</h6> <input type="number" id="firstNumber"><br> <input type="number" id="secondNumber"><br> <div id="operations"> <button name="opr">+</button> <button name="opr">-</button> <button name="opr">X</button> <button name="opr">/</button> <br> </div> <button id="clear">Clear</button> <p id="result"></p> <h6>Dynamic UI manipulation with data obtained via fetch</h6> <input type="number" id="userID"> <button onClick="getUser()">Get user</button> <button onClick="getAllUsers()">Get all</button> <br> <div id="singleUser"></div> <div id="allUsers"></div> <script src="calculator.js" type="text/javascript"></script> <script src="fetch.js" type="text/javascript"></script> 

In your loop, setting innerHTML replaces the content each time. 在循环中,设置innerHTML每次都会替换内容。 If you want to append, consider creating new nodes. 如果要追加,请考虑创建新节点。

// Create new paragraph
var name = document.createElement("p");
// Set text content to name value
name.appendChild(document.createTextNode(data[i].name));
// Append paragraph to #allUsers element
document.getElementById("allUsers").appendChild(name);
// Create new paragraph
var phone = document.createElement("p");
// Set text content to phone value
phone.appendChild(document.createTextNode(data[i].phone));
// Append paragraph to #allUsers element
document.getElementById("allUsers").appendChild(phone);

You have a problem in your loop. 您的循环中有问题。 See the below code which take the appending to the DOM out of that loop. 请参阅下面的代码,该代码将附加到DOM的内容排除在循环之外。

  var users = ""; // So that you will not initialize it every time you iterate the loop
  data.forEach(function(key) {
    users += "<p>" + "Name: " + key.name + "</p>";
    users += "<p>" + "Phone: " + key.phone + "</p>";        
    console.log(key.name);
  });
  document.getElementById("allUsers").innerHTML = users; // So that you will change the DOM/ UI only once with all the date.

Analyse: 分析:

Since you are initializing and changing your users variable in each iteration it will only have the value for that iteration. 由于您要在每次迭代中初始化和更改users变量,因此它将仅具有该迭代的值。 That is why you ended up having the last persons name. 这就是为什么您最终拥有姓氏的原因。 (This will be corrected if you are appending to a different DOM location each time, but too complex) (如果您每次都附加到一个不同的DOM位置,但是太复杂了,这将得到纠正。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM