Перебрать список массивов json

Мы только что начали 3. семестр две недели назад и изучаем базовые манипуляции с событиями/домами/выборкой.

Я должен получить данные из https://jsonplaceholder.typicode.com/users и получить все имена и номера телефонов.

Итак, вот что я сделал:

/* 
 * 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.info(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.info(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>

Как видите, мне удалось получить отдельных пользователей, что не было проблемой, но попытка получить несколько строк данных кажется мне проблемой. Я пробовал 3 разных способа, все они дают мне только последнего человека в массиве, хотя, если я печатаю его на консоли, он дает мне все это.

Пожалуйста помогите.

Это потому, что вы продолжаете заменять содержимое allUsers HTML-кодом, представляющим одного пользователя. Возможно, вы захотите добавлять новое содержимое каждый раз в цикле вместо замены.

James 13.02.2019 18:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
195
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Это простая логическая ошибка, связанная с тем, как вы выводите данные. Вы поставили:

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

внутри вашего цикла. Это означает, что каждый раз, когда ваш цикл запускается, он устанавливает значение «allUsers» в строку users, которая заменяет все, что было в этом пространстве ранее. Кроме того, каждый раз, когда ваш цикл выполняется, вы также сбрасываете строку users и включаете в нее только пользователя, полученного из текущей итерации цикла. Делая обе эти вещи, вы отбрасываете все предыдущие данные. Это происходит достаточно быстро, чтобы все, что вы видите на экране, было последним (хотя технически все остальные отображались в течение наносекунды, прежде чем были перезаписаны!).

Вам просто нужно убедиться, что users сохраняется в течение всего времени существования цикла (и что вы добавляете к нему, а не перезаписываете его), и что вы не пытаетесь поместить эти данные в свой <div>, пока не соберете все этого.

Вот исправленная версия:

/* 
 * 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.info(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>

Вам нужно инициализировать строку результата вне цикла и установить значение 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.info(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>

В вашем цикле установка innerHTML заменяет содержимое каждый раз. Если вы хотите добавить, рассмотрите возможность создания новых узлов.

// 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);

Это кажется слишком сложным по сравнению с другими ответами, но спасибо за альтернативный способ сделать это :)

dumbprogrammer 13.02.2019 19:00

@JesperChristensen имейте в виду, что если вы хотите установить HTML-код напрямую, убедитесь, что вы санируете свой ввод, чтобы вас не забанили.

AJcodez 07.03.2019 16:45

Все ваши проблемы здесь (обычно): document.getElementById("allUsers").innerHTML = all;

Строка document.getElementById("allUsers").innerHTML позволяет вам напрямую получить доступ к строковому содержимому элемента DOM. В вашем случае вам нужно добавить несколько строк в этот DOM, поэтому вам просто нужно заменить аффектацию на аффектацию добавления. Просто измените = на +=.

Вот изменения, которые вам нужно сделать:

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

Вы также можете сделать более элегантное решение:

let html = "";

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

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

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

Я не проверял код, но он должен работать!

Просто для ваших знаний, вы также должны узнать, где использовать var и let:

  • var следует использовать для глобальных переменных, потому что они могут быть доступны из любого места с помощью window.hello (если ваша переменная имеет имя «hello»).
  • let следует использовать для локальных переменных, потому что они могут быть доступны только в той же области видимости.

Получил много ответов, все с одинаковыми или похожими ответами, спасибо за бонусную информацию :)

dumbprogrammer 13.02.2019 18:59

У тебя проблема в цикле. См. приведенный ниже код, который выводит добавление к 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.info(key.name);
  });
  document.getElementById("allUsers").innerHTML = users; // So that you will change the DOM/ UI only once with all the date.

Анализ:

Поскольку вы инициализируете и изменяете свою переменную users на каждой итерации, она будет иметь значение только для этой итерации. Вот почему у вас получилось последнее имя человека. (Это будет исправлено, если вы каждый раз добавляете к другому местоположению DOM, но это слишком сложно)

Спасибо большое, теперь все понятно :)

dumbprogrammer 13.02.2019 18:58

Другие вопросы по теме