vue.js вставить блок для каждого 6-го элемента цикла - PullRequest
0 голосов
/ 28 января 2019

У меня есть рендеринг списка карт через цикл.Каждый третий элемент col (bootstrap) я добавляю в строку div.Теперь мне нужно добавить еще один элемент col (баннерный блок) для каждого 6-го элемента.Для рендеринга что-то вроде этого:

enter image description here

Как я могу это реализовать?

Мой код сейчас

<div class="row" v-for="i in Math.ceil(offers.length / 3)">
    <div class="col-xl-4 col-lg-4 col-md-6 col-sm-12 col-12" v-for="offer in offers.slice((i-1)*3, i*3)">
        <h2>{{offer.name}}</h2>
        <h2>{{offer.desc}}</h2>
    </div>
</div>

Ответы [ 6 ]

0 голосов
/ 29 января 2019

Спасибо всем, я принял решение Roy J, пересобрать для моего случая и получить результат.Мой код:

<template>
  <div class="section-space80 results-col" >
    <div class="container" >
      <div class="row">
          <div class="col-md-12">
            <div class="wrapper-content bg-white pinside40">
              <div class="row" v-for="row in rows">
                <div v-for="offer in row" class="col-xl-4 col-lg-4 col-md-6 col-sm-12 col-12">
                  <div class="lender-listing" v-if="offer.type && offer.type === 'Banner'">
                    <div class="lender-head">
                        Banner
                    </div>
                  </div>
                  <div class="lender-listing" v-if="offer.mfoName">
                    <div class="lender-head">
                        <div class="lender-logo">Offer</div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
      </div>
    </div>
  </div>
</template>

<script>
  const chunk = (arr, size) =>
  arr
  .reduce((acc, _, i) =>
    (i % size) ?
    acc :
    [...acc, arr.slice(i, i + size)], []);

  import axios from 'axios'
  export default {
    data() {
      return {
        showOffers: true,
        loanOffers: [],
        isVisible: false,
        loadMore: true,
        offset: 0,
        rows: ''

      }
    },

    methods: {
      getOffersList: function () {
        let dataElements = this
        dataElements.loading = true
        axios.get('/api/v1/getUserOffers')
          .then(function (response) {
            dataElements.loanOffers = response.data
            const withBanners = chunk(dataElements.loanOffers, 5).map((arr) => [...arr, {name: 'banner', type: 'Banner'}]).reduce((a, b) => a.concat(b));
            dataElements.rows = chunk(withBanners, 3);
          })
      },
    },
    beforeMount(){
      this.getOffersList()
    }
  }

</script>
0 голосов
/ 29 января 2019

Рекомендую использовать flex, если это возможно.Таким образом, код будет выглядеть так: http://jsfiddle.net/n89dbo37/

new Vue({
  el: '#app',
  data() {
    return {
        items: _.times(20, i => ({type: 'offer'})),
    };
  },
  computed: {
    itemsWithBanners() {
      let result = [];
      this.items.forEach((item, idx) => {
        if (idx && idx % 5 === 0) {
            result.push({type: 'banner'});
        }
        result.push(item);
      });
      return result;
    },
  },
});
0 голосов
/ 28 января 2019

Я бы порекомендовал вам меньше программировать в представлении и больше в модели представления.Создайте computed, который разбивает ваши данные на серии предложений и баннеров, а также на строки, а затем использует эти данные простым способом.

const chunk = (arr, size) =>
  arr
  .reduce((acc, _, i) =>
    (i % size) ?
    acc :
    [...acc, arr.slice(i, i + size)], []);
    
new Vue({
  el: '#app',
  data: {
    offers: []
  },
  computed: {
    rows() {
      const withBanners = chunk(this.offers, 5).map((arr) => [...arr, {name: 'banner', type: 'Banner'}]).reduce((a, b) => a.concat(b), []);

      return chunk(withBanners, 3);
    }
  },
  mounted() {
    setTimeout(() => {
      this.offers = [{
        name: 'offer'
      },
      {
        name: 'offer'
      },
      {
        name: 'offer'
      },
      {
        name: 'offer'
      },
      {
        name: 'offer'
      },
      {
        name: 'offer'
      },
      {
        name: 'offer'
      },
      {
        name: 'offer'
      },
      {
        name: 'offer'
      },
      {
        name: 'offer'
      },
      {
        name: 'offer'
      }
    ];
    }, 500);
  }
});
#app {
  display: grid;
}

.row {
  display: grid;
  grid-gap: 2rem;
  grid-template-columns: repeat(3, auto);
  justify-content: left;
}

.box {
  width: 8rem;
  height: 8rem;
}

.banner {
  background-color: #f9c;
}

.offer {
  background-color: #99f;
}
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <div class="row" v-for="row in rows">
    <div class="col-xl-4 col-lg-4 col-md-6 col-sm-12 col-12" v-for="item in row">
      <div v-if="item.type === 'Banner'" class="banner box">
        <h2>{{item.name}}</h2>
      </div>
      <div v-else class="offer box">
        <h2>{{item.name}}</h2>
      </div>
    </div>
  </div>
</div>
0 голосов
/ 28 января 2019

для цикла:

    <div class="mycol" v-for="(offer,ind) in offers">
      <template v-if="ind % 5 == 0">
       <h2>banner</banner>
      </template>
      <template v-else>
       <h2>{{offer.name}}</h2>
       <h2>{{offer.desc}}</h2>
      </template>
    </div>

для новой строки для каждого третьего столбца вы можете использовать css

.mycol:nth-child(3n+1){
 clear:left;
}
0 голосов
/ 28 января 2019

Я предполагаю, что вы хотите добавить баннер каждые 6 элементов, но вы хотите показать 6-й.Я бы обработал это на моем объекте данных, вставив в него баннер.Легче.Вы можете разделить ваш массив таким образом.

let firstPart = myData.slice(0,5)
let lastPart = myData.slice(5,)

let newData = [...firstPart, banner, ...lastPart]

Теперь вам просто нужно делать это каждые 6 элементов.

0 голосов
/ 28 января 2019

Это должно делать именно то, что вы хотите .. Мне пришлось немного манипулировать данными, потому что язык шаблонов Vue не предназначен для обработки логики для этого варианта использования

HTML

<div id="app">
  <div v-for="items in rows" class="row">
    <div v-for="item in items" class="col-xl-4 col-lg-4 col-md-6 col-sm-12 col-12">{{item}}</div>
  </div>
</div>

SCRIPT

created () {
    while (this.items.length > 0) {
      const howMany = (this.rows.length % 3 === 0) ? 3 : 2
      const row = this.items.splice(0, howMany)
      if (howMany === 2) row.push('banner')
      this.rows.push(row)

    }
},

https://jsfiddle.net/jamesharrington/k6c0rgL3/17/

...