v-for 似乎改变了数组顺序

v-for seems to change the array order

数据Object:

{
    "headers": {
        "location": "Location",
        "postcode": "Postcode",
        "contributors": "Contributors",
        "contributions": "Contributions",
        "percentage": "Percentage"
    },
    "rows": [
        {
            "postcode": "3018",
            "contributors": 2,
            "contributions": 2,
            "location": "Seaholme",
            "percentage": 67
        },
        {
            "postcode": "3013",
            "contributors": 1,
            "contributions": 1,
            "location": "Yarraville West",
            "percentage": 33
        }
    ]
}

模板:

<thead>
<tr>
    <th v-for="(v, k) in data.result.headers" :key="k">
    {{ v }}
    </th>
</tr>
</thead>
<tbody>
<tr v-for="(row, i) in data.result.rows" :key="i">
    <td :key="j" v-for="(col, j) in row">
        {{ col }}
    </td>
</tr>
</tbody>

输出:

所以 table header 和 body 是两个独立的 objects。虽然 header 似乎遵循顺序,但行 objects 却没有。我怎样才能确保它们始终正确对齐?

您可以创建 computed 属性 的 rows。这将是相同的列表,但 keysheader 键的顺序排列。这是一个可能的解决方案:

new Vue({
  el: "#app",
  data: () => ({
    "headers": { "location": "Location", "postcode": "Postcode", "contributors": "Contributors", "contributions": "Contributions", "percentage": "Percentage" },
    "rows": [
      { "postcode": "3018", "contributors": 2, "contributions": 2, "location": "Seaholme", "percentage": 67 },
      { "postcode": "3013", "contributors": 1, "contributions": 1, "location": "Yarraville West", "percentage": 33 }
    ]
  }),
  computed: {
    orderedRows() {
      const headers = Object.keys(this.headers);
      return this.rows.map(row => 
        headers.reduce((orderedRow, key) => 
          ({ ...orderedRow, [key]: row[key] })
        , {})
      );
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <table>
    <thead>
      <tr>
        <th v-for="(v, k) in headers" :key="k">{{ v }}</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(row, i) in orderedRows" :key="i">
        <td v-for="(col, j) in row" :key="j">{{ col }}</td>
      </tr>
    </tbody>
  </table>
</div>

受@CertainPerformance 评论启发的另一种可能方式:

new Vue({
  el: "#app",
  data: () => ({
    "headers": { "location": "Location", "postcode": "Postcode", "contributors": "Contributors", "contributions": "Contributions", "percentage": "Percentage" },
    "rows": [
      { "postcode": "3018", "contributors": 2, "contributions": 2, "location": "Seaholme", "percentage": 67 },
      { "postcode": "3013", "contributors": 1, "contributions": 1, "location": "Yarraville West", "percentage": 33 }
    ]
  }),
  computed: {
    headerKeys() {
      return Object.keys(this.headers);
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <table>
    <thead>
      <tr>
        <th v-for="(v, k) in headers" :key="k">{{ v }}</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(row, i) in rows" :key="i">
        <td v-for="(header, j) in headerKeys" :key="j">{{ row[header] }}</td>
      </tr>
    </tbody>
  </table>
</div>