Heim  >  Artikel  >  Web-Frontend  >  Erstellen Sie mit Vue wiederverwendbare Paginierungskomponenten

Erstellen Sie mit Vue wiederverwendbare Paginierungskomponenten

不言
不言Original
2018-03-31 17:38:301041Durchsuche

Paging-Komponenten sind sehr häufige Komponenten in Webprojekten. Informationen zur Grundstruktur und zur zugehörigen Ereignisüberwachung finden Sie in diesem Artikel.

Ressourcen-Paging in Webanwendungen ist nicht möglich Nur großartig für die Leistung, aber auch aus Sicht der Benutzererfahrung sehr nützlich. In diesem Artikel erfahren Sie, wie Sie mit Vue eine dynamische und nutzbare Paginierungskomponente erstellen.

Grundstruktur

Die Paginierungskomponente sollte es dem Benutzer ermöglichen, auf die erste und letzte Seite zuzugreifen, sich vorwärts und rückwärts zu bewegen und direkt zu wechseln die Schlussseite.

Die meisten Anwendungen stellen jedes Mal eine API-Anfrage, wenn der Benutzer die Seite wechselt. Wir müssen sicherstellen, dass die Komponente dies zulässt, aber wir möchten eine solche Anfrage nicht innerhalb der Komponente stellen. Auf diese Weise stellen wir sicher, dass Komponenten in der gesamten Anwendung wiederverwendbar sind und Anforderungen in der Betriebs- oder Serviceschicht gestellt werden. Wir können dies tun, indem wir ein Ereignis anhand der Nummer der Seite auslösen, auf die der Benutzer geklickt hat.

Es gibt mehrere Möglichkeiten, die Paginierung auf API-Endpunkten zu implementieren. Für dieses Beispiel gehen wir davon aus, dass die API uns die Anzahl der Ergebnisse für jede Seite, die Gesamtzahl der Seiten und die aktuelle Seite mitteilt. Dies werden unsere dynamischen Requisiten sein.

Wenn die API dagegen nur die Gesamtzahl der Datensätze angibt, können wir die Anzahl der Seiten berechnen, indem wir die Anzahl der Ergebnisse durch die Anzahl der Ergebnisse pro Seite dividieren: totalResults / resultsPerPage .

Wir möchten eine Schaltfläche zur ersten Seite, zur vorherigen Seite, zum Seitennummernbereich, zur nächsten Seite und zur letzten Seite rendern:

[erste] [nächste] [1] [2 ] [3 ] [vorheriges] [letztes]

Zum Beispiel ein Effekt wie im Bild unten:

Obwohl wir eine Reihe von Seiten rendern möchten , möchte aber nicht alle verfügbaren Seiten rendern. Lassen Sie uns eine Requisite für die sichtbarsten Schaltflächen in unserer Komponente festlegen.

Da wir nun wissen, was die Komponente tun soll und welche Daten sie benötigt, können wir die HTML-Struktur und die erforderlichen Requisiten einrichten.


<template id="pagination">
  <ul class="pagination">
    <li>
      <button type="button">« First</button>
    </li>
    <li>
      <button type="button">«</button>
    </li>
    <!-- 页数的范围 -->
    <li>
      <button type="button">Next »</button>
    </li>
    <li>
      <button type="button">»</button>
    </li>
  </ul>
</template>
Vue.component(&#39;pagination&#39;, {
  template: &#39;#pagination&#39;,
  props: {
    maxVisibleButtons: {
      type: Number,
      required: false,
      default: 3
    },
    totalPages: {
      type: Number,
      required: true
    },
    total: {
      type: Number,
      required: true
    },
    currentPage: {
      type: Number,
      required: true
    }
  }
})


Der obige Code registriert eine Paginierungskomponente. Wenn diese Komponente aufgerufen wird:


<p id="app">
  <pagination></pagination>
</p>


Der Effekt, den Sie zu diesem Zeitpunkt sehen, ist wie folgt:


Beachten Sie, dass in Damit die Komponenten besser aussehen und der Komponente ein wenig Stil verleihen.

Ereignisüberwachung

Jetzt müssen wir die übergeordnete Komponente benachrichtigen, wenn der Benutzer auf die Schaltfläche klickt, auf welche Schaltfläche der Benutzer geklickt hat.

Wir müssen für jede Schaltfläche einen Ereignis-Listener hinzufügen. Die v-on-Direktive ermöglicht das Abhören von DOM-Ereignissen. In diesem Beispiel verwende ich die V-On-Verknüpfung, um auf Klickereignisse zu warten.

Um den übergeordneten Knoten zu benachrichtigen, verwenden wir die Methode $emit, um ein Ereignis mit einem Seitenklick auszusenden.

Wir stellen außerdem sicher, dass der Paging-Button nur dann einen aktuellen Status hat, wenn die Seite verfügbar ist. Zu diesem Zweck wird v-bind verwendet, um den Wert des deaktivierten Attributs an die aktuelle Seite zu binden. Wir verwenden immer noch die Tastenkombination :v-bind: .

Um unsere Vorlage sauber zu halten, verwenden wir das berechnete Attribut, um zu prüfen, ob die Schaltfläche deaktiviert ist. Die Verwendung von „computed“ wird ebenfalls zwischengespeichert. Das bedeutet, dass mehrere Zugriffe auf dieselbe berechnete Eigenschaft das zuvor berechnete Ergebnis zurückgeben, ohne dass die Funktion erneut ausgeführt werden muss, solange sich „currentPage“ nicht ändert.


<template id="pagination">
  <ul class="pagination">
    <li>
      <button type="button" @click="onClickFirstPage" :disabled="isInFirstPage">« First</button>
    </li>
    <li>
      <button type="button" @click="onClickPreviousPage" :disabled="isInFirstPage">«</button>
    </li>
    <li v-for="page in pages">
      <button type="button" @click="onClickPage(page.name)" :disabled="page.isDisabled"> {{ page.name }}</button>
    </li>
    <li>
      <button type="button" @click="onClickNextPage" :disabled="isInLastPage">Next »</button>
    </li>
    <li>
      <button type="button" @click="onClickLastPage" :disabled="isInLastPage">»</button>
    </li>
  </ul>
</template>

Vue.component(&#39;pagination&#39;, {
  template: &#39;#pagination&#39;,
  props: {
    maxVisibleButtons: {
      type: Number,
      required: false,
      default: 3
    },
    totalPages: {
      type: Number,
      required: true
    },
    total: {
      type: Number,
      required: true
    },
    currentPage: {
      type: Number,
      required: true
    }
  },
  computed: {
    isInFirstPage: function () {
      return this.currentPage === 1
    },
    isInLastPage: function () {
      return this.currentPage === this.totalPages
    }
  },
  methods: {
    onClickFirstPage: function () {
      this.$emit(&#39;pagechanged&#39;, 1)
    },
    onClickPreviousPage: function () {
      this.$emit(&#39;pagechanged&#39;, this.currentPage - 1)
    },
    onClickPage: function (page) {
      this.$emit(&#39;pagechanged&#39;, page)
    },
    onClickNextPage: function () {
      this.$emit(&#39;pagechanged&#39;, this.currentPage + 1)
    },
    onClickLastPage: function () {
      this.$emit(&#39;pagechanged&#39;, this.totalPages)
    }
  }
})


Übergeben Sie beim Aufruf der Paginierungskomponente totalPages sowie total und currentPage an die Komponente:


<p id="app">
  <pagination :total-pages="11" :total="120" :current-page="currentPage"></pagination>
</p>

let app = new Vue({
  el: &#39;#app&#39;,
  data () {
    return {
      currentPage: 2
    }
  }
})


Das Ausführen des obigen Codes führt zu einem Fehler:


Nicht schwierig Wir haben festgestellt, dass in der Paginierungskomponente Seiten fehlen. Aus dem, was zuvor eingeführt wurde, können wir leicht erkennen, dass wir den Wert von Seiten berechnen müssen.


Vue.component(&#39;pagination&#39;, {
  template: &#39;#pagination&#39;,
  props: {
    maxVisibleButtons: {
      type: Number,
      required: false,
      default: 3
    },
    totalPages: {
      type: Number,
      required: true
    },
    total: {
      type: Number,
      required: true
    },
    currentPage: {
      type: Number,
      required: true
    }
  },
  computed: {
    isInFirstPage: function () {
      return this.currentPage === 1
    },
    isInLastPage: function () {
      return this.currentPage === this.totalPages
    },
    startPage: function () {
      if (this.currentPage === 1) {
        return 1
      }
      if (this.currentPage === this.totalPages) {
        return this.totalPages - this.maxVisibleButtons + 1
      }
      return this.currentPage - 1
    },
    endPage: function () {
      return Math.min(this.startPage + this.maxVisibleButtons - 1, this.totalPages)
    },
    pages: function () {
      const range = []
      for (let i = this.startPage; i <= this.endPage; i+=1) {
        range.push({
          name: i,
          isDisabled: i === this.currentPage
        })
      }
      return range
    }
  },
  methods: {
    onClickFirstPage: function () {
      this.$emit(&#39;pagechanged&#39;, 1)
    },
    onClickPreviousPage: function () {
      this.$emit(&#39;pagechanged&#39;, this.currentPage - 1)
    },
    onClickPage: function (page) {
      this.$emit(&#39;pagechanged&#39;, page)
    },
    onClickNextPage: function () {
      this.$emit(&#39;pagechanged&#39;, this.currentPage + 1)
    },
    onClickLastPage: function () {
      this.$emit(&#39;pagechanged&#39;, this.totalPages)
    }
  }
})


Das zu diesem Zeitpunkt erhaltene Ergebnis meldet keinen Fehler mehr. Sie werden den folgenden Effekt im Browser sehen:


Stile hinzufügen

Jetzt implementiert unsere Komponente alle Funktionen, die wir ursprünglich wollten, und Es wurden einige Stile hinzugefügt, damit es eher wie eine Paginierungskomponente und nicht nur wie eine Liste aussieht.

Wir möchten außerdem, dass Benutzer die Seite, auf der sie sich befinden, eindeutig identifizieren können. Lassen Sie uns die Farbe der Schaltfläche ändern, die die aktuelle Seite darstellt.

Dazu können wir die Objektsyntax verwenden, um die HTML-Klasse an die Schaltfläche der aktuellen Seite zu binden. Beim Binden eines Klassennamens mithilfe der Objektsyntax wechselt Vue automatisch die Klasse, wenn sich der Wert ändert.

虽然 v-for 中的每个块都可以访问父作用域范围,但是我们将使用 method 来检查页面是否处于 active 状态,以便保持我们的 templage 干净。


Vue.component(&#39;pagination&#39;, {
  template: &#39;#pagination&#39;,
  props: {
    maxVisibleButtons: {
      type: Number,
      required: false,
      default: 3
    },
    totalPages: {
      type: Number,
      required: true
    },
    total: {
      type: Number,
      required: true
    },
    currentPage: {
      type: Number,
      required: true
    }
  },
  computed: {
    isInFirstPage: function () {
      return this.currentPage === 1
    },
    isInLastPage: function () {
      return this.currentPage === this.totalPages
    },
    startPage: function () {
      if (this.currentPage === 1) {
        return 1
      }
      if (this.currentPage === this.totalPages) {
        return this.totalPages - this.maxVisibleButtons + 1
      }
      return this.currentPage - 1
    },
    endPage: function () {
      return Math.min(this.startPage + this.maxVisibleButtons - 1, this.totalPages)
    },
    pages: function () {
      const range = []
      for (let i = this.startPage; i <= this.endPage; i+=1) {
        range.push({
          name: i,
          isDisabled: i === this.currentPage
        })
      }
      return range
    }
  },
  methods: {
    onClickFirstPage: function () {
      this.$emit(&#39;pagechanged&#39;, 1)
    },
    onClickPreviousPage: function () {
      this.$emit(&#39;pagechanged&#39;, this.currentPage - 1)
    },
    onClickPage: function (page) {
      this.$emit(&#39;pagechanged&#39;, page)
    },
    onClickNextPage: function () {
      this.$emit(&#39;pagechanged&#39;, this.currentPage + 1)
    },
    onClickLastPage: function () {
      this.$emit(&#39;pagechanged&#39;, this.totalPages)
    },
    isPageActive: function (page) {
      return this.currentPage === page;
    }
  }
})


接下来,在 pages 中添加当前状态:


<li v-for="page in pages">
  <button type="button" @click="onClickPage(page.name)" :disabled="page.isDisabled" :class="{active: isPageActive(page.name)}"> {{ page.name }}</button>
</li>


这个时候你看到效果如下:

 

但依然还存在一点点小问题,当你在点击别的按钮时, active 状态并不会随着切换:

 

继续添加代码改变其中的效果:


let app = new Vue({
  el: &#39;#app&#39;,
  data () {
    return {
      currentPage: 2
    }
  },
  methods: {
    onPageChange: function (page) {
      console.log(page)
      this.currentPage = page;
    }
  }
})


在调用组件时:


<p id="app">
  <pagination :total-pages="11" :total="120" :current-page="currentPage" @pagechanged="onPageChange"></pagination>
</p>


这个时候的效果如下了:

 

到这里,基本上实现了咱想要的分页组件效果。

无障碍化处理

熟悉Bootstrap的同学都应该知道,Bootstrap中的组件都做了无障碍化的处理,就是在组件中添加了WAI-ARIA相关的设计。比如在分页按钮上添加 aria-label 相关属性:

 

在我们这个组件中,也相应的添加有关于WAI-ARIA相关的处理:


<template id="pagination">
  <ul class="pagination" aria-label="Page navigation">
    <li>
      <button type="button" @click="onClickFirstPage" :disabled="isInFirstPage" aria-label="Go to the first page">« First</button>
    </li>
    <li>
      <button type="button" @click="onClickPreviousPage" :disabled="isInFirstPage" aria-label="Previous">«</button>
    </li>
    <li v-for="page in pages">
      <button type="button" @click="onClickPage(page.name)" :disabled="page.isDisabled" :aria-label="`Go to page number ${page.name}`"> {{ page.name }}</button>
    </li>
    <li>
      <button type="button" @click="onClickNextPage" :disabled="isInLastPage" aria-label="Next">Next »</button>
    </li>
    <li>
      <button type="button" @click="onClickLastPage" :disabled="isInLastPage" aria-label="Go to the last page">»</button>
    </li>
  </ul>
</template>


这样有关于 aria 相关的属性就加上了:

 

最终的效果如下,可以点击下面的连接访问:


https://codepen.io/airen/pen/mxMLrG

相关推荐:

vue构建一个自动建站项目

vue构建多页面应用实例代码分享


Das obige ist der detaillierte Inhalt vonErstellen Sie mit Vue wiederverwendbare Paginierungskomponenten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn