Table header 来自 Svelte JSON 的数据 table

Table header data from JSON in Svelte table

我正在研究 Svelte 和 sb-admin-svelte 项目。我正在使用 JSON 中的 API 中的一些示例数据,到目前为止我已经在工作了,但我的问题是如何从 JSON 数据中自动获取关键项在 HTML?

中解析为 table header

这是我目前拥有的:

JSON

[
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
      "name": "Romaguera-Crona",
      "catchPhrase": "Multi-layered client-server neural-net",
      "bs": "harness real-time e-markets"
    }
  },
  {
    "id": 2,
    "name": "Ervin Howell",
    "username": "Antonette",
    "email": "Shanna@melissa.tv",
    "address": {
      "street": "Victor Plains",
      "suite": "Suite 879",
      "city": "Wisokyburgh",
      "zipcode": "90566-7771",
      "geo": {
        "lat": "-43.9509",
        "lng": "-34.4618"
      }
    },
    "phone": "010-692-6593 x09125",
    "website": "anastasia.net",
    "company": {
      "name": "Deckow-Crist",
      "catchPhrase": "Proactive didactic contingency",
      "bs": "synergize scalable supply-chains"
    }
  },
  {
    "id": 3,
    "name": "Clementine Bauch",
    "username": "Samantha",
    "email": "Nathan@yesenia.net",
    "address": {
      "street": "Douglas Extension",
      "suite": "Suite 847",
      "city": "McKenziehaven",
      "zipcode": "59590-4157",
      "geo": {
        "lat": "-68.6102",
        "lng": "-47.0653"
      }
    },
    "phone": "1-463-123-4447",
    "website": "ramiro.info",
    "company": {
      "name": "Romaguera-Jacobson",
      "catchPhrase": "Face to face bifurcated interface",
      "bs": "e-enable strategic applications"
    }
  }
...

JS

<script>
  import Table from "sveltestrap/src/Table.svelte";
  import { onMount } from "svelte";

  let users = [];

  onMount(async () => {
    const res = await fetch(`https://jsonplaceholder.typicode.com/users`);
    users = await res.json();

    console.log(users);
  });

  const tableHeading = ["ID", "Name", "Username", "email"];
  
</script>

<Table bordered responsive>
  <thead>
    <tr>
      {#each tableHeading as heading}
        <th>{heading}</th>
      {/each}
    </tr>
  </thead>
  <tbody>

    {#each users as user}
      <tr>
        <th scope="row">{user.id}</th>
        <td>{user.name}</td>
        <td>{user.username}</td>
        <td>{user.email}</td>
      </tr>
    {/each}
  </tbody>
</Table>

输出到这个:

这很好,但我想弄清楚的是如何从 JSON 数据(例如 "id", "name" "username", "email)中获取 tableHeading 数据以自动填充到 {#each tableHeading as heading}.

这是你想做的吗? REPL

<script>
    import Table from "sveltestrap/src/Table.svelte";
    import { onMount } from "svelte";

    async function fetchUsers() {
        const res = await fetch(`https://jsonplaceholder.typicode.com/users`);
        return await res.json();
    }   
</script>

{#await fetchUsers() then users}
<Table bordered responsive>
    <thead>
        <tr>
            {#each Object.keys(users[0]).slice(0,4) as heading}
            <th>{heading}</th>
            {/each}
        </tr>
    </thead>
    <tbody>

        {#each users as user}
        <tr>
            <th scope="row">{user.id}</th>
            <td>{user.name}</td>
            <td>{user.username}</td>
            <td>{user.email}</td>
        </tr>
        {/each}
    </tbody>
</Table>
{/await}

但为什么不根据给定的列数自动填充 table 内容 REPL

<script>
    import Table from "sveltestrap/src/Table.svelte";
    import { onMount } from "svelte";

    async function fetchUsers() {
        const res = await fetch(`https://jsonplaceholder.typicode.com/users`);
        return await res.json();
    }

    const columns = 4

</script>

{#await fetchUsers() then users}
<Table bordered responsive>
    <thead>
        <tr>
            {#each Object.keys(users[0]).slice(0,columns) as heading}
            <th>{heading}</th>
            {/each}
        </tr>
    </thead>
    <tbody>
        {#each users as user}
        <tr>
            {#each Object.values(user).slice(0,columns) as value, index}
                {#if index===0}
                    <th scope="row">{value}</th>
                {:else}
                    <td>{value}</td>
                {/if}
            {/each}
        </tr>
        {/each}
    </tbody>
</Table>
{/await}

对于 table body 内的内部 #each 循环,可以使用新的 svelte:element 代替(但在这种情况下并不是更好的选择)

{#each Object.values(user).slice(0,columns+1) as value, index}
    <svelte:element this={index === 0 ? 'th': 'td'}
                    scope={index === 0 ? 'row' : undefined}
                    >
        {value}
    </svelte:element>
{/each}

但更灵活方便的方法是像您已经做的那样,通过定义的 table 标题填充所有内容,并在此基础上填充 table body。像这样不需要的值可以简单地省略并且顺序很容易改变 REPL

<script>
    import Table from "sveltestrap/src/Table.svelte";
    import { onMount } from "svelte";

    async function fetchUsers() {
        const res = await fetch(`https://jsonplaceholder.typicode.com/users`);
        return await res.json();
    }

    const tableHeading = ["ID", "Name", "Website", "email", "Username", "Phone"];

</script>

{#await fetchUsers() then users}
<Table bordered responsive>
    <thead>
        <tr>
            {#each tableHeading as heading}
            <th>{heading}</th>
            {/each}
        </tr>
    </thead>
    <tbody>
        {#each users as user}
        <tr>
            {#each tableHeading as key, index}
                {@const k = key.toLowerCase()}
                {#if index===0}
                    <th scope="row">{user[k]}</th>
                {:else}
                    <td>{user[k]}</td>
                {/if}
            {/each}
        </tr>
        {/each}
    </tbody>
</Table>
{/await}