jQuery - 如何在无序列表中根据需要显示来自 GitHub API 的元素?

jQuery - How to show elements from GitHub API as desired in an unordered list?

我正在尝试使用 jQuery(AJAX) 从 GitHub API 获取一些数据,并附加它在静态网页中。下面是我的 HTML 和 JS 片段。

        $(document).ready(function(){
            $.ajax({
                url: 'https://api.github.com/repos/FearlessPython/Basics-of-Python',
            }).done(function(repo){
                $('#heading').html(`${repo.name}<hr>`);
                $('#stats').html(`
                    <strong>Stars</strong>: ${repo.stargazers_count} <br>
                    <strong>Watchers</strong>: ${repo.watchers_count} <br>
                    <strong>Language</strong>: ${repo.language} <br>
                    <strong>Open Issues</strong>: ${repo.open_issues_count} <br>
                    <strong>License</strong>: ${repo.license.name}<br>
                `);
            });
            $.ajax({
                method: "GET",
                url: "https://api.github.com/repos/FearlessPython/Basics-of-Python/contributors",
                dataType: "json"
            }).done(function(data){
                $.each(data, function(index, url){
                    $.ajax({
                        url: data[index].url
                    }).done(function(individual_contributor){
                        // console.log(data[index].url);
                        $('ul#users').append(`
                            <li><strong>${individual_contributor.name}</strong></li>
                            <li><strong>Bio:</strong> ${individual_contributor.bio}</li>
                            <li><strong>Public Repos:</strong> ${individual_contributor.public_repos}</li>
                            <li><strong>Followers:</strong> ${individual_contributor.followers}</li>
                            <li><strong>Following:</strong> ${individual_contributor.following}</li>
                        `)
                    });
                });
                $.map(data, function(contributor, i){
                    // contrb.push(contributor);
                    $('ol#contributors').append(`
                    <li><a href="${contributor.html_url}" target="_blank">${contributor.login}</a></li>

                    <img src = "${contributor.avatar_url}" style = "float: right;" width=10%>   
                    <ul id="users"></ul>
                    `);
                });
            });
        });
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
</head>
<body>Here, dynamic statistics are available regarding this repository in GitHub.

    <div id="statistics">
        <h3 id="heading"></h3>
        <ul id="stats"></ul>
        <h4>Contributors</h4><hr>
        <ol id="contributors">
            <!-- <ul id="users"></ul> -->
        </ol>
    </div>
</body>
</html>

你可以看到,在每个用户下,同样的事情一次又一次地迭代。使用 .html() 而不是 .append() 会覆盖第一次迭代数据,并且所有内容都会被最新迭代的数据替换。理想的结果应该是这样的:

我也尝试使用 for 循环,但同样的事情发生了。我试图从最近几天解决它,但无法解决。我刚开始使用 jQuery 和 AJAX.

注意:如果 GitHub API 请求超过您的要求,那么您将无法看到上述代码片段的结果。所以我也附上一张网页现状的图片。

获得贡献者列表后,您将执行两次迭代。 $.each, 在其中您发出请求以获取贡献者详细信息,这些详细信息将附加到带有 id='users' 的容器中。 (那还不存在!)

$.each(data, function(index, url){
   // request contributor details
}

$.map 将登录名和头像附加到列表以及容器 <ul id='users'>

$.map(data, function(contributor, i){
    $('ol#contributors').append(`
     <li><a href="${contributor.html_url}" target="_blank">${contributor.login}</a></li>
     <img src = "${contributor.avatar_url}" style = "float: right;" width=10%>   
     <ul id="users"></ul>`  // this will cause you trouble
);
});

现在,id 在文档中应该是唯一的,因此附加具有相同 id 的额外元素将无法按预期工作。

看,您有一个竞争条件,其中您的贡献者详细信息处理程序取决于您尚未创建的元素。无论如何,当它解析时,它的内容将附加到在查找 $('#users') 时找到的任何元素,很可能是 DOM.

中的第一个元素

四舍五入:

  • 仅对贡献者列表执行一次迭代
  • 将贡献者详细信息附加到相应的用户<ul>
  • 不要对要在列表中重复的容器使用 ID(或者至少计算它的 ID 而不是对其进行硬编码)

当您获得列表时,我会使用 for..of 进行迭代。然后在每个循环中我将声明 <ul> 元素(变为块范围)并使用该引用在子请求解析时附加用户详细信息。

  for (let contributor of contributors) {
    // block scoped
    let userDetailsElement = $('<ul class="users"></ul>');

    $('ol#contributors')
      .append(userHeader(contributor))
      .append(userDetailsElement);

    $.getJSON(contributor.url)
     .then( individual_contributor => {
      // I know   which <ul> I'm appending to
        userDetailsElement.append(
              contributorDetailsHtml(individual_contributor)
        );
    });
  }

在下面的代码片段中,我将 jQuery 的回调声明为异步的,因此我也可以像

一样等待贡献者详细信息
let individual_contributor = await $.getJSON(contributor.url);

userDetailsElement.append(
              contributorDetailsHtml(individual_contributor)
        );

等待每个用户的详细信息意味着请求将 运行 顺序进行,而触发一个 thenable 请求将并行进行。如果您要查询具有数百个贡献者的存储库,那么选择可能会有所不同,这不仅是因为性能,还因为您会受到限制并且 dom 的一部分不会呈现。

const repoUrl = 'https://api.github.com/repos/FearlessPython/Basics-of-Python';

function repoStatsHtml(repo) {
  return `
    <strong>Stars</strong>: ${repo.stargazers_count} <br>
    <strong>Watchers</strong>: ${repo.watchers_count} <br>
    <strong>Language</strong>: ${repo.language} <br>
    <strong>Open Issues</strong>: ${repo.open_issues_count} <br>
    <strong>License</strong>: ${repo.license.name}<br>
    `;
}

function contributorDetailsHtml(individual_contributor) {
  return `
    <li><strong>${individual_contributor.name}</strong></li>
    <li><strong>Bio:</strong> ${individual_contributor.bio}</li>
    <li><strong>Public Repos:</strong> ${individual_contributor.public_repos}</li>
    <li><strong>Followers:</strong> ${individual_contributor.followers}</li>
    <li><strong>Following:</strong> ${individual_contributor.following}</li>
                        `;
}

function userHeaderHtml(contributor) {
  return `
    <li><a href="${contributor.html_url}" class="login" target="_blank">${contributor.login}</a></li>
    <img src = "${contributor.avatar_url}" class="avatar">   
                    `;
}
$(document).ready(async function() {
  $.getJSON(repoUrl).done(function(repo) {
    $('#heading').html(`${repo.name}<hr>`);
    $('#stats').html(repoStatsHtml(repo));
  });
  let contributors = await $.getJSON(`${repoUrl}/contributors`);

  for (let contributor of contributors) {
    let userDetailsElement = $('<ul class="users"></ul>');
    $('ol#contributors')
      .append(userHeaderHtml(contributor))
      .append(userDetailsElement);
    $.getJSON(contributor.url).then(individual_contributor => {
      userDetailsElement.append(
        contributorDetailsHtml(individual_contributor)
      );
    });
  }

});
.users {
  min-width: 90px;
  min-height: 90px;
  margin-bottom: 0.5em;
}

.avatar {
  float: right;
  width: 10%;
}

.login {
  margin-top: 0.5em;
  font-size: 1.1em;
  text-decoration: none;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
</head>

<body>Here, dynamic statistics are available regarding this repository in GitHub.

  <div id="statistics">
    <h3 id="heading"></h3>
    <ul id="stats"></ul>
    <h4>Contributors</h4>
    <hr>
    <ol id="contributors">
    </ol>
  </div>
</body>

</html>