簡介
設想一下,如果商品條目數(shù)量很多,假設有100條襟企,如果我們一次性拉下來,是很影響性能的狮含。所以我們需要為商品列表添加分頁功能顽悼。本篇主要實現(xiàn)以下目的:
- 后端分頁功能邏輯實現(xiàn)
- 前端分頁功能邏輯實現(xiàn)
1. 后端分頁功能邏輯實現(xiàn)
這里我們有如下約定;
- 后端需要接收參數(shù)page和pageSize。
- page表示請求第幾頁數(shù)據(jù)几迄。
- pageSize表示每頁返回的數(shù)目蔚龙。
- 按pageSize分頁并返回指定頁數(shù)的數(shù)據(jù)。
修改routes/goods.js文件如下:
/* GET goods */
router.get('/', function (req, res, next) {
// 只有接口請求帶參數(shù)sort=priceDown才會按價格降序
let sort = req.query['sort'] === 'priceDown'?-1:1;
let startPrice = req.query['startPrice'];
let endPrice = req.query['endPrice'];
let page = parseInt(req.query['page']);
let pageSize = parseInt(req.query['pageSize']);
// 價格篩選處理邏輯
startPrice = startPrice? parseInt(startPrice):0;
endPrice = endPrice?parseInt(endPrice):undefined;
console.log(startPrice, endPrice);
let params = {};
if (endPrice) {
params = {salePrice: {$gt: startPrice, $lte: endPrice}};
} else {
params = {salePrice: {$gt: startPrice}};
}
// 分頁處理邏輯
if (!(page > 0 && pageSize > 0)) {
res.json({
code: '801',
msg: '請求參數(shù)有誤'
});
return;
}
let skip = (page - 1)*pageSize;
// 查詢起始價(不包含)到結(jié)尾價(包含)區(qū)間的商品,并分頁返回
let query = Good.find(params).skip(skip).limit(pageSize);
query.sort({salePrice: sort});
query.exec((err, doc) => {
if (err) {
res.json({
code: '900',
msg: err.message || '服務器錯誤'
})
} else {
res.json({
code: '000',
msg: '',
result: {
count: doc.length,
list: doc
}
})
}
});
});
2. 前端分頁功能邏輯實現(xiàn)
這里我們不再詳述與后端分離開發(fā)的邏輯映胁,直接使用已經(jīng)開發(fā)好的后端接口來看效果木羹。
step1 在前端寫死分頁參數(shù)請求數(shù)據(jù)并展示
此處由于后端返回的數(shù)據(jù)結(jié)構(gòu)有了變化,為了看到效果,我們首先要更改一下前端數(shù)據(jù)處理邏輯坑填。
export default {
data () {
return {
prdList: [], // 產(chǎn)品列表
// 價格過濾列表
priceFilterList: [
{
startPrice: 0,
endPrice: 100
},
{
startPrice: 100,
endPrice: 500
},
{
startPrice: 500,
endPrice: 2000
},
{
startPrice: 2000
}
],
priceChecked: 'all', // 選中的價格過濾列表項
filterPrice: null, // 選中的價格過濾列表對象
isShowFilterBy: false, // 是否展示過濾列表彈窗
isShowOverLay: false, // 是否展示遮罩層
page: 1,
pageSize: 8,
sortChecked: 'default',
isPriceUp: true
}
},
computed: {
isPriceArrowUp () {
return !this.isPriceUp
}
},
components: {
PageHeader,
PageBread,
PageFooter
},
created () {
this.getPrdList()
},
methods: {
// 請求接口獲取產(chǎn)品列表數(shù)據(jù)
getPrdList () {
queryPrdObj = Object.assign({}, this.filterPrice, {page: this.page, pageSize: this.pageSize, sort: this.sortChecked})
axios.get('/api/goods', {params: queryPrdObj}).then((res) => {
console.log('res', res)
let data = (res && res.data) || {}
if (data.code === '000') {
let result = data.result || {}
this.prdList = result.list || []
console.log('prdList', this.prdList)
} else {
alert(`err:${data.msg || '系統(tǒng)錯誤'}`)
}
})
},
// 選取價格過濾列表項
checkPriceFilter (index) {
this.priceChecked = index
this.filterPrice = index === 'all' ? null : this.priceFilterList[index]
this.getPrdList()
this.closeFilterBy()
},
// 展示過濾列表彈窗
showFilterBy () {
this.isShowFilterBy = true
this.isShowOverLay = true
},
// 關閉過濾列表彈窗
closeFilterBy () {
this.isShowFilterBy = false
this.isShowOverLay = false
},
checkSort (val) {
this.sortChecked = val
if (val === 'priceUp' || val === 'priceDown') {
this.isPriceUp = !this.isPriceUp
} else {
this.isPriceUp = true
}
this.getPrdList()
}
}
}
step2 使用vue-infinite-loading進行上拉加載
關于vue-infinite-loading使用方法見官網(wǎng)抛人。
安裝;
npm install vue-infinite-loading --save
修改GoodsList.vue文件如下:
<template>
<div>
<PageHeader></PageHeader>
<PageBread>
<span>Goods</span>
</PageBread>
<div class="accessory-result-page accessory-page">
<div class="container">
<div class="filter-nav">
<span class="sortby">Sort by:</span>
<a href="javascript:void(0)" class="default" :class="{'cur': sortChecked === 'default'}" @click="checkSort('default')">Default</a>
<a href="javascript:void(0)" class="price" :class="{'cur': sortChecked === 'priceUp' || sortChecked === 'priceDown'}" @click="checkSort(isPriceUp?'priceDown':'priceUp')">Price
<span v-if="isPriceArrowUp">↑</span>
<span v-else>↓</span>
<!--<svg class="icon icon-arrow-short">-->
<!--<symbol id="icon-arrow-short" viewBox="0 0 25 32">-->
<!--<title>arrow-short</title>-->
<!--<path class="path1" d="M24.487 18.922l-1.948-1.948-8.904 8.904v-25.878h-2.783v25.878l-8.904-8.904-1.948 1.948 12.243 12.243z"></path>-->
<!--</symbol>-->
<!--<use xlink:href="#icon-arrow-short"></use>-->
<!--</svg>-->
</a>
<a href="javascript:void(0)" class="filterby stopPop" @click="showFilterBy">Filter by</a>
</div>
<div class="accessory-result">
<!-- filter -->
<div class="filter stopPop" id="filter" :class="{'filterby-show': isShowFilterBy}">
<dl class="filter-price">
<dt>Price:</dt>
<dd><a href="javascript:void(0)" :class="{'cur': priceChecked === 'all'}" @click="checkPriceFilter('all')">All</a></dd>
<dd v-for="(item, index) in priceFilterList" :key="index">
<a v-if="item.endPrice" href="javascript:void(0)" :class="{'cur': priceChecked === index}" @click="checkPriceFilter(index)">{{item.startPrice}} - {{item.endPrice}}</a>
<a v-else href="javascript:void(0)" :class="{'cur': priceChecked === index}" @click="checkPriceFilter(index)">> {{item.startPrice}}</a>
</dd>
</dl>
</div>
<!-- search result accessories list -->
<div class="accessory-list-wrap">
<div class="accessory-list col-4">
<ul>
<li v-for="item in prdList" :key="item.productId">
<div class="pic">
<a href="#"><img v-lazy="`../../../static/${item.productImage}`" alt=""></a>
</div>
<div class="main">
<div class="name">{{item.productName}}</div>
<div class="price">{{item.salePrice}}</div>
<div class="btn-area">
<a href="javascript:;" class="btn btn--m">加入購物車</a>
</div>
</div>
</li>
</ul>
</div>
<infinite-loading @infinite="infiniteHandler">
<span slot="no-more">
No more ...
</span>
</infinite-loading>
</div>
</div>
</div>
</div>
<div class="md-overlay" v-show="isShowOverLay" @click="closeFilterBy"></div>
<PageFooter></PageFooter>
</div>
</template>
<script>
import PageHeader from '../../components/PageHeader'
import PageBread from '../../components/PageBread'
import PageFooter from '../../components/PageFooter'
import axios from 'axios'
import InfiniteLoading from 'vue-infinite-loading'
let queryPrdObj = {}
export default {
data () {
return {
prdList: [], // 產(chǎn)品列表
// 價格過濾列表
priceFilterList: [
{
startPrice: 0,
endPrice: 100
},
{
startPrice: 100,
endPrice: 500
},
{
startPrice: 500,
endPrice: 2000
},
{
startPrice: 2000
}
],
priceChecked: 'all', // 選中的價格過濾列表項
filterPrice: null, // 選中的價格過濾列表對象
isShowFilterBy: false, // 是否展示過濾列表彈窗
isShowOverLay: false, // 是否展示遮罩層
page: 1,
pageSize: 8,
sortChecked: 'default',
isPriceUp: true
}
},
computed: {
isPriceArrowUp () {
return !this.isPriceUp
}
},
components: {
PageHeader,
PageBread,
PageFooter,
InfiniteLoading
},
created () {
// this.getPrdList()
},
methods: {
// 請求接口獲取產(chǎn)品列表數(shù)據(jù)
getPrdList ($state) {
queryPrdObj = Object.assign({}, this.filterPrice, {page: this.page, pageSize: this.pageSize, sort: this.sortChecked})
axios.get('/api/goods', {params: queryPrdObj}).then((res) => {
console.log('res', res)
this.page++
let data = (res && res.data) || {}
if (data.code === '000') {
let result = data.result || {}
this.prdList = this.prdList.concat(result.list || [])
if (result.count === this.pageSize) {
$state.loaded()
} else {
$state.complete()
}
} else {
alert(`err:${data.msg || '系統(tǒng)錯誤'}`)
$state.complete()
}
})
},
// 選取價格過濾列表項
checkPriceFilter (index) {
this.priceChecked = index
this.filterPrice = index === 'all' ? null : this.priceFilterList[index]
this.getPrdList()
this.closeFilterBy()
},
// 展示過濾列表彈窗
showFilterBy () {
this.isShowFilterBy = true
this.isShowOverLay = true
},
// 關閉過濾列表彈窗
closeFilterBy () {
this.isShowFilterBy = false
this.isShowOverLay = false
},
checkSort (val) {
this.sortChecked = val
if (val === 'priceUp' || val === 'priceDown') {
this.isPriceUp = !this.isPriceUp
} else {
this.isPriceUp = true
}
this.getPrdList()
},
infiniteHandler ($state) {
this.getPrdList($state)
}
}
}
</script>
總結(jié)
到此,商品列表頁的查詢展示邏輯基本上完成了脐瑰。
我們提交代碼:
- six-tao
git status
git diff
git commit -am 'add vue-infinite-loading'
git push
- six-tao-server
git status
git diff
git commit -am 'paging logic done'
git push