Vue組件實(shí)戰(zhàn):分頁(yè)組件開(kāi)發(fā)
介紹
在Web應(yīng)用程序中,分頁(yè)功能是必不可少的一個(gè)組件。一個(gè)好的分頁(yè)組件應(yīng)該展示簡(jiǎn)潔明了,功能豐富,而且易于集成和使用。
在本文中,我們將介紹如何使用Vue.js框架來(lái)開(kāi)發(fā)一個(gè)高度可定制化的分頁(yè)組件。我們將通過(guò)代碼示例來(lái)詳細(xì)說(shuō)明如何使用Vue組件開(kāi)發(fā)。
技術(shù)棧
Vue.js 2.xJavaScript (ES6)HTML5和CSS3
開(kāi)發(fā)環(huán)境
Node.js v8.9.3npm v5.5.1Vue.js v2.5.2
分頁(yè)組件需求
通過(guò)props接收總頁(yè)面數(shù)(total)和當(dāng)前頁(yè)面數(shù)(current)屬性可以配置顯示的最大頁(yè)碼數(shù)(maxShown)可以配置按鈕顯示的文本 (prevText和nextText) 和按鈕樣式點(diǎn)擊頁(yè)碼可以切換到相應(yīng)的頁(yè)面當(dāng)前頁(yè)碼高亮顯示當(dāng)前頁(yè)面沒(méi)有前一頁(yè)時(shí),忽略上一頁(yè)按鈕的點(diǎn)擊事件當(dāng)前頁(yè)面沒(méi)有后一頁(yè)時(shí),忽略下一頁(yè)按鈕的點(diǎn)擊事件
設(shè)計(jì)思路和代碼實(shí)現(xiàn)
根據(jù)需求,我們將分頁(yè)組件拆分為多個(gè)小組件來(lái)實(shí)現(xiàn)。我們需要?jiǎng)?chuàng)建以下3個(gè)小組件:
- Pagination.vue
主分頁(yè)組件,負(fù)責(zé)分頁(yè)數(shù)據(jù)和邏輯的處理。向子組件傳遞分頁(yè)信息和響應(yīng)子組件的事件。
- Button.vue
該組件為按鈕組件,用于創(chuàng)建分頁(yè)按鈕。
- Page.vue
該組件用于創(chuàng)建單個(gè)頁(yè)面塊,包含頁(yè)面標(biāo)號(hào)和狀態(tài)。頁(yè)面塊可以是當(dāng)前頁(yè)面或非當(dāng)前頁(yè)面。
接下來(lái),讓我們使用代碼來(lái)實(shí)現(xiàn)以上3個(gè)組件。
- Pagination.vue
<template> <div class="pagination-container"> <button-prev :current="current" @onPrev="prev"></button-prev> <page v-for="page in pages" :key="page" :page="page" :is-selected="page === current" @on-page-selected="selectPage"></page> <button-next :current="current" :total="total" @onNext="next"></button-next> </div> </template> <script> import ButtonPrev from './ButtonPrev.vue'; import ButtonNext from './ButtonNext.vue'; import Page from './Page.vue'; export default { components: { ButtonPrev, ButtonNext, Page }, props: { total: { type: Number, default: 10 }, current: { type: Number, default: 1 }, maxShown: { type: Number, default: 5 }, prevText: { type: String, default: '上一頁(yè)' }, nextText: { type: String, default: '下一頁(yè)' } }, computed: { pages () { const start = Math.max(1, this.current - Math.floor(this.maxShown / 2)); const end = Math.min(this.total, start + this.maxShown - 1); return Array.from({ length: end - start + 1 }, (v, k) => start + k); } }, methods: { selectPage (page) { if (this.current === page) return; this.current = page; this.$emit('onPageChanged', page); }, prev () { if (this.current > 1) { this.selectPage(this.current - 1); } }, next () { if (this.current < this.total) { this.selectPage(this.current + 1); } } } } </script>
登錄后復(fù)制
上面的代碼中,我們首先import了ButtonPrev、ButtonNext和Page組件。接著,用props方式獲取了total, current, maxShown, prevText和nextText屬性,并定義了計(jì)算屬性pages,根據(jù)當(dāng)前頁(yè)碼(current)和最大頁(yè)碼數(shù)(maxShown)得到一個(gè)包含頁(yè)碼數(shù)的數(shù)組,以在組件中呈現(xiàn)。
我們還定義了selectPage方法,在該方法中,如果頁(yè)碼(page)與當(dāng)前頁(yè)碼(current)相同,則返回或不做任何事情。否則,將新頁(yè)碼發(fā)出給父組件。
prev()和next()方法用于處理上一頁(yè)和下一頁(yè)事件,并防止event被響應(yīng)。
- ButtonPrev.vue
<template> <button class="btn-previous" :disabled="current === 1" @click="onPrev()"> {{ prevText }} </button> </template> <script> export default { props: { prevText: { type: String, default: '上一頁(yè)' }, current: { type: Number, default: 1 } }, methods: { onPrev () { this.$emit('onPrev'); } } } </script> <style scoped> .btn-previous { border: none; color: #333; display: inline-block; font-size: 16px; padding: 6px 12px; margin-right: 5px; background-color:#fff; cursor: pointer; border-radius: 2px; box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1); } .btn-previous:disabled { color: #ccc; cursor: default; } </style>
登錄后復(fù)制
上述代碼中,我們首先通過(guò)props獲取了當(dāng)前頁(yè)碼(current)和上一頁(yè)按鈕的文本(prevText)屬性。在模版中,使用類綁定(disabled)控制按鈕使用狀態(tài)。定義了一個(gè)onPrev方法,該方法觸發(fā)父組件的onPrev事件。
- ButtonNext.vue
<template> <button class="btn-next" :disabled="current === total" @click="onNext()"> {{ nextText }} </button> </template> <script> export default { props: { total: { type: Number, default: 10 }, nextText: { type: String, default: '下一頁(yè)' }, current: { type: Number, default: 1 } }, methods: { onNext () { this.$emit('onNext'); } } } </script> <style scoped> .btn-next { border: none; color: #333; display: inline-block; font-size: 16px; padding: 6px 12px; margin-left: 5px; background-color: #fff; cursor: pointer; border-radius: 2px; box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1); } .btn-next:disabled { color: #ccc; cursor: default; } </style>
登錄后復(fù)制
上述代碼中,我們將ButtonPrev.vue的代碼復(fù)制了一份,稍微改了一下文本和判斷條件。
- Page.vue
<template> <button :class="{ current: isSelected }" class="btn-page" @click="onPageSelected(page)"> {{ page }} </button> </template> <script> export default { props: { page: { type: Number, required: true }, isSelected: { type: Boolean, default: false } }, methods: { onPageSelected () { this.$emit('onPageSelected', this.page); } } } </script> <style scoped> .btn-page { border: none; color: #333; display: inline-block; font-size: 16px; padding: 6px 12px; margin-left: 5px; background-color: #fff; cursor: pointer; border-radius: 2px; box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1); } .btn-page.current { background-color: #0078d7; color: #fff; } </style>
登錄后復(fù)制
上述代碼中,我們通過(guò)props獲取了該頁(yè)碼的值(page)和按鈕的isSelected屬性。在模板中,使用類綁定(“current”)高亮顯示選中的頁(yè)面。
我們還定義了一個(gè)onPageSelected方法,該方法會(huì)觸發(fā)父組件的onPageSelected事件。
最后,這些組件可以在任何Vue.js應(yīng)用程序中的template中使用,如下所示:
<template> <div> <pagination :total="total" :current="current" :maxShown="maxShown" :prevText="prevText" :nextText="nextText" @onPageChanged="onPageChanged"></pagination> <ul> <li v-for="(item, index) in items" :key="index">{{ item.name }}</li> </ul> </div> </template> <script> import Pagination from './Pagination.vue'; export default { components: { Pagination }, data () { return { current: 1, maxShown: 10, prevText: '上一頁(yè)', nextText: '下一頁(yè)', total: 10, pageSize: 10, items: [{ name: 'Item 1' }, { name: 'Item 2' }, { name: 'Item 3' }] } }, methods: { onPageChanged (page) { console.log('Page changed to: ', page); // 當(dāng)前頁(yè)面數(shù)據(jù)請(qǐng)求 } } } </script>
登錄后復(fù)制
上述代碼中,我們引入了Pagination組件,并將其作為template中的父組件。我們還將total, current和maxShown綁定到組件,以便獲取到它們的值。在onPageChanged方法中,我們可以處理頁(yè)面更改事件,并根據(jù)當(dāng)前頁(yè)碼請(qǐng)求相應(yīng)的數(shù)據(jù)。