table 中的交替行颜色使用 vuejs 的双 v-for 构建

Alternate row color in table build with double v-for with vuejs

我想更改 HTML table 中偶数行的背景颜色。当我有一个具有已知列名的 table 和一个用于行的 v-for 时,这是有效的,但现在我有未知的列和行,所以我必须做一个双 v-for 并且我可以'用我以前的方法无法完成它。

HTML:

<template>
  <table class="tbl" ref="thisTable">
    <thead>
      <tr>
        <th v-for="columnName in tableData.columnsNames"> {{Object.values(columnName)[0]}} </th>
      </tr>
    </thead>
    <tbody v-for="row in tableData.rows">
      <tr>
        <td v-for="colName in tableData.columnsNames">{{ row[Object.keys(colName)[0]] }}</td>
      </tr>
    </tbody>
  </table>
</template>

CSS

<style scoped>
  .tbl {
    border-collapse: collapse;
    margin: 20px 0 0 20px;
    font-size: 1em;
    font-family: Poppins;
    min-width: 400px;
    box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
  }
  .tbl thead tr {
    background-color: #980000;
    color: #ffffff;
    text-align: left;
  }
  .tbl th,
  .tbl td {
      padding: 6px 10px;
      text-align: center;
  }
  .tbl tbody tr {
      border-bottom: 1px solid #dddddd;
  }
  .tbl tbody tr:nth-child(even) {
      background-color: #f3f3f3;
  }
</style>

tableData结构:

{'columnsNames': [{"field1: "Field 1"}, {"field2: "Field 2"}], 'rows': [{"field1: "data11", "field2:"data12"}, {"field1: "data21", "field2:"data22"}]}

你可以试试用 js 代替 css:

new Vue({
  el: "#demo",
  data() {
    return {
      tableData: {'columnsNames': [{"field1": "Field 1"}, {"field2": "Field 2"}, {"field3": "Field 3"}, {"field4": "Field 4"}], 'rows': [{"field1": "data11", "field2":"data12", "field3":"data13", "field4":"data14"}, {"field1": "data21", "field2":"data22", "field3": "data23", "field4":"data24"},]}
    }
  },
  methods: {
    //  find out if index of row is even
    isEven(num) {
      return (num % 2) == 0;
    }
  }
})
.tbl {
  border-collapse: collapse;
  margin: 20px 0 0 20px;
  font-size: 1em;
  font-family: Poppins;
  min-width: 400px;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
}
.tbl thead tr {
  background-color: #980000;
  color: #ffffff;
  text-align: left;
}
.tbl th,
.tbl td {
    padding: 6px 10px;
    text-align: center;
}
.tbl tbody tr {
    border-bottom: 1px solid #dddddd;
}

.even {
  background-color: #f3f3f3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
  <table class="tbl" ref="thisTable">
    <thead>
      <tr>
        <th v-for="(columnName, i) in tableData.columnsNames" :key="i"> {{Object.values(columnName)[0]}} </th>
      </tr>
    </thead>
    <tbody v-for="(row, idx) in tableData.rows" :key="idx">
      <tr>
                <!--  call method and attach class -->
        <td :class="!isEven(idx) ? 'even' : ''" v-for="(colName, i) in tableData.columnsNames" :key="i">{{ row[Object.keys(colName)[0]] }}</td>
      </tr>
    </tbody>
  </table>
</div>

问题是外层 v-for 放在 <tbody> 上,所以每一行都用新的 <tbody>:

渲染
<table class="tbl">
  <thead>
    <tr><th>Field 1</th><th>Field 2</th></tr>
  </thead>
  <tbody> <!-- row -->
    <tr><td>data11</td><td>data12</td></tr>
  </tbody>
  <tbody> <!-- row -->
    <tr><td>data21</td><td>data22</td></tr>
  </tbody>
</table>

所以 tbody tr:nth-child(even) 永远不会匹配,因为每个 <tbody> 只有一个 <tr>.

解决方案

把外面的 v-for 放在 <tr> 而不是 <tbody>:

<table>
  <tbody>
     
    <tr v-for="row in tableData.rows">
      <td v-for="colName in tableData.columnsNames">{{ row[Object.keys(colName)[0]] }}</td>
    </tr>
  </tbody>
</table>

demo