vue.js v-for для двух строк таблицы

Vue 2, без веб-пакета. Я хочу отображать две trs за раз, для основной и подробной расширяемой строки. Это то, чего я пытаюсь достичь:

<table>
   <tbody>
     <div v-for="item in items">
         <tr></tr>
         <tr class="detail-row"></tr>
     </div>
   </tbody>
</table>

Проблема в том, что <div> является недопустимым дочерним элементом tbody. Как отобразить два <tr> на каждой итерации цикла for?


person user3599803    schedule 27.02.2018    source источник
comment
Можете ли вы расширить вопрос с помощью варианта использования, что именно вы хотели реализовать?   -  person Bhojendra Rauniyar    schedule 27.02.2018


Ответы (3)


Именно так вы решаете это в браузерах, поддерживающих template.

<table>
   <tbody>
     <template v-for="item in items">
         <tr></tr>
         <tr class="detail-row"></tr>
     </template>
   </tbody>
</table>

Если вам нужно поддерживать браузеры, которые не поддерживают template, я обычно прибегаю к функции рендеринга.

Вот рабочий пример обоих.

console.clear()

new Vue({
  el: "#app",
  data: {
    items: [{
        master: "Master",
        detail: "Detail"
      },
      {
        master: "Master",
        detail: "Detail"
      },
    ]
  }
})

new Vue({
  el: "#app2",
  data: {
    items: [{
        master: "Master",
        detail: "Detail"
      },
      {
        master: "Master",
        detail: "Detail"
      },
    ]
  },
  render(h){
    // build the rows
    let rows = []
    for (let item of this.items){
      rows.push(h("tr", [h("td", [item.master])]))
      rows.push(h("tr", {class: "detail-row"}, [h("td", [item.detail])]))
    }
    
    // add rows to body
    let body = h("tbody", rows)
    
    // return the table
    return h("table", [body])
  }
})
.detail-row{
 background-color: lightgray;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<h2>Using template</h2>
<div id="app">
  <table>
    <tbody>
      <template v-for="item in items">
        <tr><td>{{item.master}}</td></tr>
        <tr class="detail-row"><td>{{item.detail}}</td></tr>
      </template>
    </tbody>
  </table>
</div>
  
<h2>Using render function</h2>
<div id="app2"></div>

person Bert    schedule 27.02.2018
comment
Но является ли шаблон допустимым дочерним узлом для tbody? Я думал, что разрешены только элементы tr - person user3599803; 27.02.2018
comment
@ user3599803 template не отображается. Обратите внимание на пример. - person Bert; 27.02.2018
comment
Да. Это совершенно верно, поскольку браузер не отображает элемент шаблона. - person Bhojendra Rauniyar; 27.02.2018
comment
Обратите внимание, что поддержка браузера не имеет значения, если вы используете файлы .vue, поскольку компилятор vue автоматически исправляет этот случай для вас. - person Ferrybig; 27.02.2018
comment
@Ferrybig Да, или шаблоны простых строк. - person Bert; 27.02.2018
comment
Спасибо, я выберу вариант «шаблон», в основном я использую строку шаблона, но иногда использую и шаблон DOM. Как я уже сказал, я не использую веб-пакеты или упаковщики, поэтому никаких файлов vue. - person user3599803; 27.02.2018
comment
Как насчет привязки :key=? ‹шаблон› не может быть набран ключом - person Piotr; 09.07.2018
comment
@bfcior Вам не нужно помещать ключ в шаблон, вы можете добавлять ключи в строки. - person Bert; 09.07.2018
comment
:key теперь требуется для элементов в итерации. Как это решить другим? - person Alen Siljak; 09.03.2020

В более новой версии VueJS требуется index. Таким образом, решение будет выглядеть

  <table>
    <tbody>
      <template v-for="(item, index) in items">
        <tr :key="index">
           <td>{{item.master}}</td>
        </tr>
        <tr :key="index" class="detail-row">
           <td>{{item.detail}}</td>
        </tr>
      </template>
    </tbody>
  </table>
person James A Mohler    schedule 28.10.2020

Если вы хотите использовать в двойном теге. Или вы хотите использовать отдельный компонент в div шаблона внутри тегов tr таблицы (как в новом компоненте), вы можете использовать style=display: содержимое в первом div, чтобы строки таблицы были встроены друг в друга.

Компонент Vue

<table> 
<template v-for="v-for="(price, index) in prices">
<div :key="price.id"  style="display: contents">
<tr><td>{{price.id}}</td><td>{{price.name}}</td></tr>
<tr col-span="2">{{price.desc}}</tr>
</div>
</template>
</table>

Или если вы хотите использовать отдельный компонент для строк

Таблица.vue

<template>
<div>
<table class="table">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
</tr>
</thead>
<tbody>
<template v-for="item in items">
<my-component :item=“item”/>
</template>
</tbody>
</table>
</div>
</template>

мой-component.vue

<template>
<div style="display: contents">
<tr>
<td>{{item.firstname}}</td>
<td>{{item.lastname}}</td>
</tr>
<tr>
<td colspan="2" >
{{item.description}}
</td>
</tr>
</div>
</template>
person Kima    schedule 15.06.2020