Vue.js分页-当前页数超过最大页数

vs3odd8k  于 7个月前  发布在  Vue.js
关注(0)|答案(1)|浏览(91)

我正在尝试在我构建的这个表中实现分页,其中包含Magic:The Gathering cards的数据。
默认状态是每页只显示5个项目,页面选择器按钮和每页结果按钮位于屏幕底部(沿着有“下一页”和“上一页”按钮用于导航)。

const app = new Vue({
  el: "#app",
  data: {
    apiUrl: "https://api.magicthegathering.io/v1/cards",
    cards: [],
    pageNumber: 1,
    resultsPerPage: 5,
    dropdownResultsPerPage: 5,
    increments: [5, 10, 15, 20, 25]
  },
  created: function() {
    var vue = this;
    axios
      .get(this.apiUrl)
      .then(function(data) {
        vue.cards = data.data.cards;
      })
      .catch(function(error) {
        console.log(error);
      });
  },
  computed: {
    startIndex: function() {
      return (this.pageNumber - 1) * this.resultsPerPage;
    },
    endIndex: function() {
      return this.startIndex + this.dropdownResultsPerPage;
    },
    numberOfPages: function() {
      return Math.ceil(this.cards.length / this.dropdownResultsPerPage);
    },
    paginatedData: function() {
      return this.cards.slice(this.startIndex, this.endIndex);
    }
  },
  methods: {
    nextPage: function() {
      this.pageNumber++;
    },
    previousPage: function() {
      this.pageNumber--;
    }
  }
});
body {
  overflow: hidden;
}

#header {
  display: flex;
  position: sticky;
  border-bottom: 1px solid black;
}

#app .content {
  overflow: auto;
  height: 300px;
  position: relative;
}

#pagination: {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  box-shadow: 0px 0px 6px 2px #fafafa;
}

[v-cloak] {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.6.0/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.8/vue.min.js"></script>
<div id="header">
  <h1>MTG Cards</h1>
</div>
<div id="app" v-cloak>
  <div class="content">
    <table>
      <thead>
        <th>Id</th>
        <th>Name</th>
        <th>Mana Cost</th>
      </thead>
      <tbody>
        <tr v-for="(card, index) in paginatedData" :key="index">
          <td>{{ card.id }}</td>
          <td>{{ card.name }}</td>
          <td>{{ card.manaCost }}</td>
        </tr>
      </tbody>
    </table>
  </div>
  <div id="pagination">
    <p>
      Page:
      <select v-model="pageNumber">
        <option v-for="(page, index) in numberOfPages" :key="index" :value="page">
          {{ page }}
        </option>
      </select>
      of {{ numberOfPages }}
      <button @click="previousPage" :disabled="pageNumber == 1">
        Previous
      </button>
      <button @click="nextPage" :disabled="pageNumber >= numberOfPages">
        Next
      </button> |
      <select v-model="dropdownResultsPerPage">
        <option v-for="(increment, index) in increments" :key="index" :value="increment">
          {{ increment }}
        </option>
      </select>
      cards per page
    </p>
  </div>
</div>

假设您将resultsPerPage设置为5,这将给予100的总页数。
现在,假设您导航到第5页(共20页),然后将resultsPerPage值更改为25。这将使总页数从20变为4,但由于您在第5页,因此无法在页码栏中看到这一点,并且页面导航会变得有点混乱。
有没有一种方法可以保持可视页码,同时在屏幕上的表格中保持相同的结果?

jk9hmnmh

jk9hmnmh1#

您面临的问题是,当每页的结果数发生变化时,当前的页码可能会超过新的总页数。
要解决此问题,您需要在resultsPerPage更改时调整当前页码,以确保其不超过新的总页数。
为此,您可以查看resultsPerPage,并相应调整pageNumber,具体实现方式如下:

const app = new Vue({
  el: "#app",
  data: {
    apiUrl: "https://api.magicthegathering.io/v1/cards",
    cards: [],
    pageNumber: 1,
    resultsPerPage: 5,
    dropdownResultsPerPage: 5,
    increments: [5, 10, 15, 20, 25]
  },
  created: function() {
    this.fetchCards();
  },
  watch: {
    dropdownResultsPerPage(newVal, oldVal) {
      const oldStartIndex = (this.pageNumber - 1) * oldVal;
      this.pageNumber = Math.floor(oldStartIndex / newVal) + 1;
      this.resultsPerPage = newVal; // Ensure resultsPerPage is updated
    }
  },
  computed: {
    startIndex: function() {
      return (this.pageNumber - 1) * this.resultsPerPage;
    },
    endIndex: function() {
      return this.startIndex + this.resultsPerPage;
    },
    numberOfPages: function() {
      return Math.ceil(this.cards.length / this.resultsPerPage);
    },
    paginatedData: function() {
      return this.cards.slice(this.startIndex, this.endIndex);
    }
  },
  methods: {
    nextPage: function() {
      if (this.pageNumber < this.numberOfPages) {
        this.pageNumber++;
      }
    },
    previousPage: function() {
      if (this.pageNumber > 1) {
        this.pageNumber--;
      }
    },
    fetchCards: function() {
      var vue = this;
      axios
        .get(this.apiUrl)
        .then(function(response) {
          vue.cards = response.data.cards;
        })
        .catch(function(error) {
          console.log(error);
        });
    }
  }
});

字符串
我为dropdownResultsPerPage添加了一个观察器。当它发生变化时,我们会根据旧的起始索引计算新的pageNumber,以使用户大致保持在相同的数据范围内。resultsPerPage也会更新以反映变化。

相关问题