v-if inside v-for - 在两列中显示项目列表

Posted

技术标签:

【中文标题】v-if inside v-for - 在两列中显示项目列表【英文标题】:V-if inside v-for - display list of items in two columns 【发布时间】:2019-04-04 04:16:21 【问题描述】:

很抱歉发布此消息,因为我可以看到许多与此类似的问题已被多次询问。以下是几乎可以帮助我的那些 - 以及为什么他们没有:

This 一个是因为计算不应该在渲染中完成,而是在方法/计算部分。这对我没有帮助。 This 一个是使用两个不同的模板,在模板标签上写 v-if。在我的情况下这似乎很愚蠢,因为这两个模板将 98% 相同。 This Medium-article 解决了一个非常接近我的问题非常。但是,-在他的情况下,这是对用户的过滤(通过计算属性解决),而不是在某个迭代中插入 sn-p 代码的 if 子句(我认为我正在寻找) .

问题

我有一个从 API 中提取的项目列表,因此数量会发生变化。我希望它们显示在两列中:

-----------------
| Item1   Item5 |
| Item2   Item6 |
| Item3   Item7 |
| Item4         |
-----------------

我正在使用 v-for 循环遍历它们。

我的尝试

    使用纯 CSS 和 display: flex

但这只能做到这一点:

-----------------
| Item1   Item2 |
| Item3   Item4 |
| Item5   Item6 |
| Item7         |
-----------------
    将 CSS 与 column-count: 2; 结合使用

但这打破了列中间元素,display: block; overflow: hidden; 和许多其他尝试。应该说,这些元素的高度是可以变化的。

    所以我放弃了使用 CSS 修复它。

如果是php,那么我会简单地做这样的事情:

<?php
if( $index == count( $items)/2 ):
  echo '</div>';
  echo '</div>';
  echo '<div class="col-md-6">';
  echo '<div class="item-container">';
endif;
?>

...但事实并非如此。我正在寻找 vue 的替代品。我试过this:

#if key === Number( items.length / 2 ) 
  </div>
  </div>
  <div class="col-md-6">
  <div class="item-container">
/if

但它不起作用。据我所知,这不是“vue 方式”。但我不知道是什么。 :-/

这样的事情存在吗?

我当前代码的简化

<div class="col-md-12">
    <div class="items-container">
        <div class="item-container" v-for="item, key in items['data']">
            <!-- A BUNCH OF ITEM-INFO -->
        </div><!-- /.item-container -->
    </div><!-- /.items-container -->
</div><!-- /.col-md-12 -->

【问题讨论】:

为了避免重复关闭,请edit your question 引用其他帖子并解释它们如何/为什么不适合您? 我现在添加了最接近解决方案的那些,以及为什么我不能使用它们 (@Phil)。 干杯。我想您不希望为items-container 设置固定高度,对吗?所以您希望第二列从基于项目数的逻辑中间点开始? 认为您可以使用条件类 `v-for="item, key, index in items['data']" v-bind:class=" clearfix: !(索引 % 2) "1 @Phil :是的,-我强烈希望不要设置高度,因为内容将从 API 中提取,所以我无法控制一堆东西被拉。所以网格应该尽可能灵活。 【参考方案1】:

我要做的是创建一个计算属性,将 items 数组划分(或分块)为适当数量的列。

这是一个使用 flexbox 布局和一个额外的 column 元素的示例。

new Vue(
  el: 'main',
  data: 
    items: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7'],
    cols: 2
  ,
  computed: 
    columns () 
      let columns = []
      let mid = Math.ceil(this.items.length / this.cols)
      for (let col = 0; col < this.cols; col++) 
        columns.push(this.items.slice(col * mid, col * mid + mid))
      
      return columns
    
  
)
.container 
  display: flex;
  border: 1px solid;

.col 
  margin: 10px;
  border: 1px solid;
  flex-grow: 1;
  display: flex;
  flex-direction: column;

.item-container 
  border: 1px solid;
  padding: 5px;
  margin: 5px;
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js"></script>
<main>
<p><label>Columns:<label> <input type="number" v-model="cols"></p>
<div class="container">
  <div class="col" v-for="column in columns">
    <div class="item-container" v-for="item in column">item</div>
  </div>
</div>
</main>

如果您想要一种不太冗长的方式来分块 items 数组,请参阅 Split array into chunks

【讨论】:

【参考方案2】:

很高兴看到有人偶然发现与我相同的问题。我必须在每列中放置 6 个项目。我将 API 响应分割成列,然后打印出来。

let allCategory = response.body.Categories.slice(); //clone
while (allCategory.length > 0) 
  let chunk = allCategory.splice(0,6);
  this.ColArray.push(chunk);
  

ColArray 是一个数组,它将包含列的数组。它看起来像这样:


  ColArray: [
    Column1: [
      Item1,
      Item2,
      Item3,
    ],
    Column2: [
      ...
    ]
  ]

在 Vue 中它只会被循环,像这样:

<div v-for="(col,colIndex) in ColArray" :key="'cate_col'+colIndex" class="col-md-2">
  <div v-for="(row,rowIndex ) in col"   :key="'cate_row'+colIndex + rowIndex" class="row">
    row
  </div>
</div>

这是一个小提琴示例:

https://jsfiddle.net/keysl183/50wL7mdz/775484/

【讨论】:

这是一个非常好的解决方法。但是,在给定的迭代中使用 Vue 不可能打印/回显/检查某些东西,这真的是真的吗?在那种情况下,我必须以某种方法或其他方式来做吗? 您可以在计算中实现拼接和切片,因此您不需要使用方法【参考方案3】:

适用于尝试实现相同结果(将项目分成列)但拆分对象而不是数组的任何人。

此解决方案基于 Phil 选择的答案。

它使用 Object.keys 循环遍历对象并使用 Object.entries 从对象中返回一个数组。无需通过 html 模板中的索引进行访问,而是通过键来访问。

new Vue(
    el: 'main',
    data: 
        items:  
          item1:  name: 'Item 1' , 
          item2:  name: 'Item 2' , 
          item3:  name: 'Item 3' ,
          item4:  name: 'Item 4' ,
          item5:  name: 'Item 5' ,
          item6:  name: 'Item 6' ,
          item7:  name: 'Item 7' ,
          item8:  name: 'Item 8' ,
          item9:  name: 'Item 9' ,
          item10:  name: 'Item 10' ,
        ,
        cols: 2
    ,
    computed: 
          columns: function() 
              let columns = [];
              let mid = Math.ceil(Object.keys(this.items).length / this.cols);

              for (let col = 0; col < this.cols; col++) 
                  columns.push(Object.entries(this.items).slice(col * mid, col * mid + mid).map(entry => entry[1]));
              
              return columns;
          
      
);
.container 
  display: flex;
  border: 1px solid;

.col 
  margin: 10px;
  border: 1px solid;
  flex-grow: 1;
  display: flex;
  flex-direction: column;

.item-container 
  border: 1px solid;
  padding: 5px;
  margin: 5px;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js"></script>
  <main>
    <p><label>Columns:<label> <input type="number" v-model="cols"></p>
    <div class="container">
      <div class="col" v-for="column in columns">
        <div class="item-container" v-for="(item, index) in Object.keys(column)">
        column[item].name</div>
      </div>
    </div>
</main>

【讨论】:

以上是关于v-if inside v-for - 在两列中显示项目列表的主要内容,如果未能解决你的问题,请参考以下文章

如何同时在两列中添加或插入多行? [复制]

在没有 v-if 和 v-for 的 Vue.js 中显示(添加、编辑)和删除多个列中的列表项

ionic 2 angular 2 在两列中分布绑定记录

Pandas - 在两列中查找具有匹配值的行并在另一列中相乘

基于可互换出现在两列中的值聚合数据?

如何选择在两列中具有相同值集的行,从而连接第三列中的值?