如何在javascript中将对象移至第一个块并将最旧的块移动到新块?

时间:2019-02-27 21:24:02

标签: javascript vue.js

我有一些数据,每次从推送程序中检索到新数据时,都必须对其进行更新。我正在使用Vue.js进行反应,并防止每次触发事件时从服务器重新加载所有内容。

我需要针对这种情况更新阵列。

/**
 *
 * 1. prevent each array chunk to store more than 4 items
 *
 * 2. if all chunk is already contains 4 items, create a new chunk,
 * unshift new data and move oldest item to the new chunk.
 *
 * ------------ example ------------
 *
 * *  const beforeUnshift = [
 * *     0 => [7, 6, 5, 4],
 * *     1 => [3, 2, 1, 0]
 * *  ];
 *
 * *  const afterUnshift = [
 * *    0 => [8, 7, 6, 5],
 * *    1 => [4, 3, 2, 1],
 * *    2 => [0]
 * *  ];
 *
 * *  const afterSecondaryUnshift = [
 * *    0 => [9, 8, 7, 6],
 * *    1 => [5, 4, 3, 2],
 * *    2 => [1, 0]
 * *  ];
 *
 * * and so on...
 */

请看一下我的代码,每个页面最多必须显示4个数据。触发事件后,它确实会更新,但是会一直更新到最底部,直到刷新页面为止。

<template>
  <div class="table-swipable" style="overflow-x: hidden;">
    <div class="swiper-wrapper">
      <div class="swiper-slide" v-for="flightChunk in chunkedFlights">
        <div class="table-responsive">
          <table class="table">
            <thead>
              <tr>
                <th class="pl-0 pr-1 border-0 text-center fit-content">
                  <div class="bg-white shadow rounded cardy-th">Flight No.</div>
                </th>
                <th class="px-1 border-0 text-center">
                  <div class="bg-white shadow rounded cardy-th">Airlines</div>
                </th>
                <th class="px-1 border-0 text-center" colspan="2">
                  <div class="bg-white shadow rounded cardy-th">Destination</div>
                </th>
                <th class="px-1 border-0 text-center" colspan="2">
                  <div class="bg-white shadow rounded cardy-th">Departure / Arrival</div>
                </th>
                <th class="pl-1 pr-0 border-0 text-center">
                  <div class="bg-white shadow rounded cardy-th">Status</div>
                </th>
              </tr>
            </thead>
            <tbody class="font-weight-bold">
              <template v-for="flight in flightChunk">
                <tr class="bg-white shadow fit-content">
                  <td class="border-0 py-4 pl-4 rounded-left">
                    <i class="fas fa-plane text-primary mr-3"></i>
                    #{{ flight.id }}
                  </td>
                  <td class="border-0 py-4 pl-4">{{ flight.airline.name }}</td>
                  <td class="border-0 py-4 pl-4 text-center">{{ flight.origin.city }}</td>
                  <td class="border-0 py-4 pl-4 text-center">{{ flight.destination.city }}</td>
                  <td class="border-0 py-4 pl-4 text-center">{{ flight.departure | removeSecond }}</td>
                  <td class="border-0 py-4 pl-4 text-center">{{ flight.arrival | removeSecond }}</td>
                  <td
                    class="border-0 py-4 pl-4 text-primary rounded-right text-center"
                  >{{ flight.status ? flight.status : 'Awaiting confirmation' }}</td>
                </tr>
                <tr class="tr-spacer"></tr>
              </template>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import Swiper from "swiper";
import moment from "moment";

export default {
  data() {
    return {
      flights: {}
    };
  },
  computed: {
    chunkedFlights() {
      return _.chunk(this.flights.data, 4);
    }
  },
  created() {
    Echo.channel("flight-created").listen("FlightCreated", ({ flights }) => {
      this.chunkedFlights[0].unshift(flights[0]);
      this.$forceUpdate();
    });
  },
  filters: {
    removeSecond(time) {
      if (!time) return "";
      return moment(time).format("hh:mm");
    }
  },
  updated() {
    var tableSwipable = new Swiper(".table-swipable", {
      centeredSlides: true,
      slidesPerView: 1,
      spaceBetween: 60,
      autoplay: {
        delay: 30000
      }
    });
  },
  mounted() {
    axios.get("/flights/public").then(response => {
      this.flights = response.data;
    });
  }
};
</script>

2 个答案:

答案 0 :(得分:0)

因此,在这种情况下,将数据与视图层分开是有意义的。如果您具有单个更新的事实来源,而不是尝试直接更新块,那么它使处理更新变得更容易。

因此,当您获得更新时,将其移至this.flights.data而不是大块中,然后让vue重新计算大块。这样可以将原始的data数组保留为唯一的真相来源,并且您每次都可以从视图中更新其中的块。

答案 1 :(得分:0)

哦,我看到frodo2975捕获到您正在转移到计算值中而不是数据中。我没注意到。这可以按您的预期工作:

new Vue({
  el: '#app',
  data: {
    flights: [
      7, 6, 5, 4, 3, 2, 1, 0
    ]
  },
  computed: {
    chunkedFlights() {
      return _.chunk(this.flights, 4);
    }
  },
  mounted() {
    setTimeout(() => {
      this.flights.unshift(8);
    }, 2000);
  }
});
#app {
  display: grid;
  grid-gap: 2rem;
  background-color: black;
  padding: 0.6rem;
}

.page {
  background-color: #ffe;
  padding: 0.6rem;
  grid-gap: 0.2rem;
  display: grid;
}

.row {
  background-color: blue;
  color: white;
  padding: 0.6rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="chunk in chunkedFlights" class="page">
    <div v-for="flight in chunk" class="row">
      {{flight}}
    </div>
  </div>
</div>