简介
本篇,我们做一些商品列表页的前端逻辑功能。
- 价格过滤列表的点击逻辑
- 价格过滤列表的露出逻辑
- 排序点击的逻辑
1. 价格过滤列表的点击逻辑
step1:价格过滤列表的字段显示。
这里,我们不做太复杂的逻辑,这些过滤字段不从后端请求,也不由用户输入,而是在前端写死。在GoodsList.vue中进行如下修改:
<div class="filter stopPop" id="filter">
<dl class="filter-price">
<dt>Price:</dt>
<dd><a href="javascript:void(0)">All</a></dd>
<dd v-for="(item, index) in priceFilterList" :key="item.index">
<a v-if="item.endPrice" href="javascript:void(0)">{{item.startPrice}} - {{item.endPrice}}</a>
<a v-else href="javascript:void(0)">> {{item.startPrice}}</a>
</dd>
</dl>
</div>
data () {
return {
prdList: [],
priceFilterList: [
{
startPrice: 0,
endPrice: 100
},
{
startPrice: 100,
endPrice: 500
},
{
startPrice: 500,
endPrice: 2000
},
{
startPrice: 2000
}
]
}
}
step2: 点击某个过滤项时会点亮并且请求数据
在GoodsList.vue中进行如下修改:
<div class="filter stopPop" id="filter">
<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>
data () {
return {
prdList: [],
priceFilterList: [
{
startPrice: 0,
endPrice: 100
},
{
startPrice: 100,
endPrice: 500
},
{
startPrice: 500,
endPrice: 2000
},
{
startPrice: 2000
}
],
priceChecked: 'all',
filterPrice: null
}
}
methods: {
getPrdList (params) {
axios.get('mock/goods', {params: params}).then((res) => {
console.log('res', res)
let data = (res && res.data) || {}
if (data.code === '000') {
this.prdList = data.result || []
console.log('prdList', this.prdList)
} else {
alert(`err:${data.msg || '系统错误'}`)
}
})
},
checkPriceFilter (index) {
this.priceChecked = index
this.filterPrice = index === 'all' ? null : this.priceFilterList[index]
this.getPrdList(this.filterPrice)
}
}
}
此时点击不同过滤项会点亮该过滤项并带上相应参数去请求获取产品列表的接口,目的达到。
2. 价格过滤列表的露出逻辑
由于页面使用响应式,当屏幕宽度过小时价格过滤列表会隐藏。此时我们要控制价格过滤列表的展现与消失逻辑。主要有以下逻辑:
- 点击FILTER BY按钮,右侧会弹出价格过滤列表,并会展现遮罩层
- 选取价格以后会带参请求产品列表数据,并关闭弹层和遮罩层
- 点击遮罩层会关闭弹层和遮罩层
实现代码如下:
<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 cur">Default</a>
<a href="javascript:void(0)" class="price">Price
<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>
</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'
export default {
data () {
return {
prdList: [], // 产品列表
// 价格过滤列表
priceFilterList: [
{
startPrice: 0,
endPrice: 100
},
{
startPrice: 100,
endPrice: 500
},
{
startPrice: 500,
endPrice: 2000
},
{
startPrice: 2000
}
],
priceChecked: 'all', // 选中的价格过滤列表项
filterPrice: null, // 选中的价格过滤列表对象
isShowFilterBy: false, // 是否展示过滤列表弹窗
isShowOverLay: false // 是否展示遮罩层
}
},
components: {
PageHeader,
PageBread,
PageFooter
},
created () {
this.getPrdList()
},
methods: {
// 请求接口获取产品列表数据
getPrdList (params) {
axios.get('mock/goods', {params: params}).then((res) => {
console.log('res', res)
let data = (res && res.data) || {}
if (data.code === '000') {
this.prdList = data.result || []
console.log('prdList', this.prdList)
} else {
alert(`err:${data.msg || '系统错误'}`)
}
})
},
// 选取价格过滤列表项
checkPriceFilter (index) {
this.priceChecked = index
this.filterPrice = index === 'all' ? null : this.priceFilterList[index]
this.getPrdList(this.filterPrice)
this.closeFilterBy()
},
// 展示过滤列表弹窗
showFilterBy () {
this.isShowFilterBy = true
this.isShowOverLay = true
},
// 关闭过滤列表弹窗
closeFilterBy () {
this.isShowFilterBy = false
this.isShowOverLay = false
}
}
}
</script>
3. 排序点击的逻辑
这里我们只设置了默认排序以及按价格升降排序,所谓的默认排序其实就是很多商城里面的综合排序,由后台根据指定算法进行计算。这里主要实现以下逻辑控制:
点击Price会改变后面的箭头,默认箭头向下,点击以后箭头向上,并向后台请求产品列表时带上sort=priceDown参数,请求回来的产品列表按价格降序排列,并且点击非排序按钮请求时也会带上sort=priceDown参数。
再点击一次箭头向下,并向后台请求产品列表时带上sort=priceUp参数,请求回来的产品列表按价格升序排列,并且点击非排序按钮请求时也会带上sort=priceUp参数。
不管何时,点击default,price箭头变为向下,并向后台请求产品列表时带上sort=default参数,请求回来的产品列表按默认顺序排列,并且点击非排序按钮请求时也会带上sort=default参数。
代码如下:
<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>
</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'
let queryPrdObj = {}
export default {
data () {
return {
prdList: [], // 产品列表
// 价格过滤列表
priceFilterList: [
{
startPrice: 0,
endPrice: 100
},
{
startPrice: 100,
endPrice: 500
},
{
startPrice: 500,
endPrice: 2000
},
{
startPrice: 2000
}
],
priceChecked: 'all', // 选中的价格过滤列表项
filterPrice: null, // 选中的价格过滤列表对象
isShowFilterBy: false, // 是否展示过滤列表弹窗
isShowOverLay: false, // 是否展示遮罩层
sortChecked: 'default',
isPriceUp: true
}
},
computed: {
isPriceArrowUp () {
return !this.isPriceUp
}
},
components: {
PageHeader,
PageBread,
PageFooter
},
created () {
this.getPrdList()
},
methods: {
// 请求接口获取产品列表数据
getPrdList () {
queryPrdObj = Object.assign(queryPrdObj, this.filterPrice, {sort: this.sortChecked})
axios.get('mock/goods', {params: queryPrdObj}).then((res) => {
console.log('res', res)
let data = (res && res.data) || {}
if (data.code === '000') {
this.prdList = data.result || []
console.log('prdList', this.prdList)
} else {
alert(`err:${data.msg || '系统错误'}`)
}
})
},
// 选取价格过滤列表项
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()
}
}
}
</script>
总结
本篇主要是一些前端业务逻辑的编码,这里的实现其实存在一个小bug,是关于筛选价格方面的,后面在在线商城项目12-商品列表页价格筛选实现一文中我做了修改。另外,那个向上箭头的svg重构没有提供,直接画svg我还也没有研究过,所以用向上和向下箭头代替了。后期我们可能会引入iconfont。下面我们提交代码:
git status
git diff
git commit -am 'goodslist logic done'
git push
网友评论