Vue3电商项目实战-分类模块5【12-二级类目-结果区-排序组件、13-二级类目-结果区-数据加载、14-二级类目-结果区-进行筛选】
文章目录
- 12-二级类目-结果区-排序组件
- 13-二级类目-结果区-数据加载
- 14-二级类目-结果区-进行筛选
12-二级类目-结果区-排序组件
目的:封装排序组件,完成排序切换效果
大致步骤:
- 定义一个组件
sub-sort
,完成基础布局 - 在
sub.vue
组件使用 - 完成切换排序时候的交换效果
落地代码:
- 1)基础布局:
src/views/category/components/sub-sort.vue
<template><div class='sub-sort'><div class="sort"><a href="javascript:;">默认排序</a> <a href="javascript:;">最新商品</a><a href="javascript:;">最高人气</a><a href="javascript:;">评论最多</a><a href="javascript:;">价格排序<i class="arrow up" /><i class="arrow down" /></a></div><div class="check"><XtxCheckbox>仅显示有货商品</XtxCheckbox><XtxCheckbox>仅显示特惠商品</XtxCheckbox></div></div>
</template>
<script>
export default {name: 'SubSort'
}
</script>
<style scoped lang='less'>
.sub-sort {height: 80px;display: flex;align-items: center;justify-content: space-between;.sort {display: flex;a {height: 30px;line-height: 28px;border: 1px solid #e4e4e4;padding: 0 20px;margin-right: 20px;color: #999;border-radius: 2px;position: relative;transition: all .3s;&.active {background: @xtxColor;border-color: @xtxColor;color: #fff;}.arrow {position: absolute;border: 5px solid transparent;right: 8px;&.up {top: 3px;border-bottom-color: #bbb;&.active {border-bottom-color: @xtxColor;}}&.down {top: 15px;border-top-color: #bbb;&.active {border-top-color: @xtxColor;}}}}}.check {.xtx-checkbox {margin-left: 20px;color: #999;}}
}
</style>
使用组件:src/views/category/sub.vue`
<template><div class='sub-category'><div class="container"><!-- 面包屑 --><SubBread /><!-- 筛选区 --><SubFilter /><!-- 结果区域 -->
+ <div class="goods-list">
+ <!-- 排序 -->
+ <SubSort />
+ <!-- 列表 -->
+ </div></div></div>
</template><script>
import SubBread from './components/sub-bread'
import SubFilter from './components/sub-filter'
+import SubSort from './components/sub-sort'
export default {name: 'SubCategory',
+ components: { SubBread, SubFilter, SubSort}
}
</script><style scoped lang='less'>
+.goods-list {
+ background: #fff;
+ padding: 0 25px;
+ margin-top: 25px;
+}
</style>
- 2)交互效果:
<template><div class='sub-sort'><div class="sort"><a :class="{active:sortParams.sortField===null}" @click="changeSort(null)" href="javascript:;">默认排序</a><a :class="{active:sortParams.sortField==='publishTime'}" @click="changeSort('publishTime')" href="javascript:;">最新商品</a><a :class="{active:sortParams.sortField==='orderNum'}" @click="changeSort('orderNum')" href="javascript:;">最高人气</a><a :class="{active:sortParams.sortField==='evaluateNum'}" @click="changeSort('evaluateNum')" href="javascript:;">评论最多</a><a @click="changeSort('price')" href="javascript:;">价格排序<i class="arrow up" :class="{active:sortParams.sortField==='price'&&sortParams.sortMethod=='asc'}" /><i class="arrow down" :class="{active:sortParams.sortField==='price'&&sortParams.sortMethod=='desc'}" /></a></div><div class="check"><XtxCheckbox v-model="sortParams.inventory">仅显示有货商品</XtxCheckbox><XtxCheckbox v-model="sortParams.onlyDiscount">仅显示特惠商品</XtxCheckbox></div></div>
</template>
<script>
import { reactive } from 'vue'
export default {name: 'SubSort',setup () {// 1. 根据后台需要的参数定义数据对象// 2. 根据数据对象,绑定组件(复选框,排序按钮)// 3. 在操作排序组件的时候,需要反馈给数据对象// sortField====>publishTime,orderNum,price,evaluateNum// sortMethod====>asc为正序 desc为倒序const sortParams = reactive({inventory: false,onlyDiscount: false,sortField: null,sortMethod: null})// 改变排序const changeSort = (sortField) => {if (sortField === 'price') {sortParams.sortField = sortFieldif (sortParams.sortMethod === null) {// 第一次点击,默认是降序sortParams.sortMethod = 'desc'} else {// 其他情况根据当前排序取反sortParams.sortMethod = sortParams.sortMethod === 'desc' ? 'asc' : 'desc'}} else {// 如果排序未改变停止逻辑 if (sortParams.sortField === sortField) returnsortParams.sortField = sortFieldsortParams.sortMethod = null}}return { sortParams, changeSort }}
}
</script>
13-二级类目-结果区-数据加载
目的:实现结果区域商品展示。
大致步骤:
- 完成结果区域商品布局
- 完成
xtx-infinite-loading
组件封装 - 使用
xtx-infinite-loading
完成数据加载和渲染
落地代码:src/views/category/sub.vue
1.基础布局
<template><div class='sub-category'><div class="container"><!-- 面包屑 --><SubBread /><!-- 筛选区 --><SubFilter /><!-- 结果区域 --><div class="goods-list"><!-- 排序 --><SubSort /><!-- 列表 --><ul><li v-for="i in 20" :key="i" ><GoodsItem :goods="{}" /></li></ul></div></div></div>
</template><script>
import SubBread from './components/sub-bread'
import SubFilter from './components/sub-filter'
import SubSort from './components/sub-sort'
import GoodsItem from './components/goods-item'
export default {name: 'SubCategory',components: { SubBread, SubFilter, SubSort, GoodsItem }
}
</script><style scoped lang='less'>
.goods-list {background: #fff;padding: 0 25px;margin-top: 25px;ul {display: flex;flex-wrap: wrap;padding: 0 5px;li {margin-right: 20px;margin-bottom: 20px;&:nth-child(5n) {margin-right: 0;}}}
}
</style>
2.无限列表加载组件 src/components/xtx-infinite-loading.vue
<template><div class="xtx-infinite-loading" ref="container"><div class="loading" v-if="loading"><span class="img"></span><span class="text">正在加载...</span></div><div class="none" v-if="finished"><span class="img"></span><span class="text">亲,没有更多了</span></div></div>
</template><script>
import { ref } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
export default {name: 'XtxInfiniteLoading',props: {loading: {type: Boolean,default: false},finished: {type: Boolean,default: false}},setup (props, { emit }) {const container = ref(null)useIntersectionObserver(container,([{ isIntersecting }], dom) => {if (isIntersecting) {if (props.loading === false && props.finished === false) {emit('infinite')}}},{threshold: 0})return { container }}
}
</script><style scoped lang='less'>
.xtx-infinite-loading {.loading {display: flex;align-items: center;justify-content: center;height: 200px;.img {width: 50px;height: 50px;background: url(../../assets/images/load.gif) no-repeat center / contain;}.text {color: #999;font-size: 16px;}}.none {display: flex;align-items: center;justify-content: center;height: 200px;.img {width: 200px;height: 134px;background: url(../../assets/images/none.png) no-repeat center / contain;}.text {color: #999;font-size: 16px;}}
}
</style>
3.定义获取数据的API src/api/category.js
/*** 获取分类下的商品(带筛选条件)* @param {Object} params - 可参考接口文档*/
export const findSubCategoryGoods = (params) => {return request('/category/goods/temporary', 'post', params)
}
4.在src/views/category/sub.vue
使用组件
<!-- 结果区域 --><div class="goods-list"><!-- 排序 --><GoodsSort /><!-- 列表 --><ul><li v-for="item in list" :key="item.id" ><GoodsItem :goods="item" /></li></ul><!-- 加载 -->
+ <XtxInfiniteLoading :loading="loading" :finished="finished" @infinite="getData" /></div>
<script>
import SubBread from './components/sub-bread'
import SubFilter from './components/sub-filter'
import SubSort from './components/sub-sort'
import GoodsItem from './components/goods-item'
import { ref, watch } from 'vue'
import { findSubCategoryGoods } from '@/api/category'
import { useRoute } from 'vue-router'
export default {name: 'SubCategory',components: { SubBread, SubFilter, SubSort, GoodsItem },setup () {// 1. 基础布局// 2. 无限加载组件// 3. 动态加载数据且渲染// 4. 任何筛选条件变化需要更新列表const route = useRoute()const loading = ref(false)const finished = ref(false)const goodsList = ref([])// 查询参数let reqParams = {page: 1,pageSize: 20}// 获取数据函数const getData = () => {loading.value = truereqParams.categoryId = route.params.idfindSubCategoryGoods(reqParams).then(({ result }) => {if (result.items.length) {goodsList.value.push(...result.items)reqParams.page++} else {// 加载完毕finished.value = true}// 请求结束loading.value = false})}// 切换二级分类重新加载watch(() => route.params.id, (newVal) => {if (newVal && route.path === ('/category/sub/' + newVal)) {goodsList.value = []reqParams = {page: 1,pageSize: 20}finished.value = false}})return { loading, finished, goodsList, getData }}
}
</script>
14-二级类目-结果区-进行筛选
目的:在做了筛选和排序的时候从新渲染商品列表。
大致步骤:
- 排序组件,当你点击了排序后 或者 复选框改变后 触发自定义事件
sort-change
传出排序参数 - 筛选组件,当你改了品牌,或者其他筛选添加,触发自定义事件
filter-change
传出筛选参数 - 在sub组件,分别绑定
sort-change
filter-change
得到参数和当前参数合并,回到第一页,清空数据,设置未加载完成,触发加载。
落地代码:
- 组件:
src/views/category/components/sub-sort.vue
// 改变排序const changeSort = (sortField) => {// 省略代码....
+ emit('sort-change', sortParams)}
<div class="check"><XtxCheckbox @change="changeCheck" v-model="sortParams.inventory">仅显示有货商品</XtxCheckbox><XtxCheckbox @change="changeCheck" v-model="sortParams.onlyDiscount">仅显示特惠商品</XtxCheckbox></div>
const changeCheck = (sortField) => {emit('sort-change', sortParams)}
- 组件
src/views/category/components/sub-filter.vue
// 获取筛选参数const getFilterParams = () => {const filterParams = {}const attrs = []filterParams.brandId = filterData.value.selectedBrandfilterData.value.saleProperties.forEach(p => {const attr = p.properties.find(attr => attr.id === p.selectedProp)if (attr && attr.id !== undefined) {attrs.push({ groupName: p.name, propertyName: attr.name })}})if (attrs.length) filterParams.attrs = attrsreturn filterParams}// 选择品牌const changeBrand = (brandId) => {if (filterData.value.selectedBrand === brandId) return filterData.value.selectedBrand = brandIdemit('filter-change', getFilterParams())}// 选中属性const changeAttr = (p, attrId) => {if (p.selectedProp === attrId) returnp.selectedProp = attrIdemit('filter-change', getFilterParams())}return { filterData, filterLoading, changeBrand, changeAttr }}
- 组件
src/views/category/sub.vue
<SubFilter @sort-change="changeFilter" />
<GoodsSort @filter-change="changeSort"/>
// 监听筛选区改变const changeFilter = (filterParams) => {reqParams = { ...reqParams, ...filterParams }reqParams.page = 1goodsList.value = []finished.value = false}// 监听排序改变const changeSort = (sortParams) => {reqParams = { ...reqParams, ...sortParams }reqParams.page = 1goodsList.value = []finished.value = false}return { loading, finished, goodsList, getData, changeFilter, changeSort }
相关文章:

Vue3电商项目实战-分类模块5【12-二级类目-结果区-排序组件、13-二级类目-结果区-数据加载、14-二级类目-结果区-进行筛选】
文章目录12-二级类目-结果区-排序组件13-二级类目-结果区-数据加载14-二级类目-结果区-进行筛选12-二级类目-结果区-排序组件 目的:封装排序组件,完成排序切换效果 大致步骤: 定义一个组件 sub-sort,完成基础布局在 sub.vue 组件…...

计算机操作系统概述
文章目录1.0 操作系统概述1.1 操作系统的目标1.2 操作系统的功能1.3 操作系统结构1.4 操作系统接口1.5 操作系统的发展1.6 操作系统的特征2.0 进程管理2.1 进程调度2.2 进程调度算法2.3 进程间通信2.4 进程间的同步2.5 软件实现互斥的方法2.6 硬件实现互斥的方法2.7 信号2.8 管…...

面试官让你说说react状态管理?
hooks 为什么不能放在条件判断里 以 setState 为例,在 react 内部,每个组件(Fiber)的 hooks 都是以链表的形式存在 memoizeState 属性中 update 阶段,每次调用 setState,链表就会执行 next 向后移动一步。如果将 setState 写在条…...

CUDA线程块的分配
为了确保能够真正地了解线程块的分配,接下来我们写一个简短的内核程序来输出线程块、线程、线程束和线程全局标号到屏幕上。现在,除非你使用的是 3.2 版本以上的 SDK否则内核中是不支持 printf的。因此,我们可以将数据传送回 CPU 端然后输出到…...

史密斯圆图
在射频、微波中,常常使用史密斯圆图来做阻抗匹配。在不涉及复杂的数学推导,仍能把圆图用起来。 比如,共轭匹配。 RL1jX,需要找到-jX来抵消jX,消掉虚部之后,只留下实部,最终等效为RL‘1。 史密…...

Spring国际化实现
Java国际化 Java使用Unicode来处理所有字符。 Locales 国际化主要涉及的是数字、日期、金额等。 有若干个专门负责格式处理的类。为了对格式进行控制,可以使用Locale类。它描述了: 一种语言一个位置(通常包含)一段脚本(可选,自Java SE7开…...

10- 天猫用户复购预测 (机器学习集成算法) (项目十) *
项目难点 merchant: 商人重命名列名: user_log.rename(columns{seller_id:merchant_id}, inplaceTrue)数据类型转换: user_log[item_id] user_log[item_id].astype(int32)主要使用方法: xgboost, lightbm竞赛地址: 天猫复购预测之挑战Baseline_学习赛_天池大赛-阿里云天池…...
对于《MySQL 实战45讲》的理解
一.理论 一条SQL执行过程 连接器分析器优化器执行器 索引 索引的出现其实就是为了提高数据查询的效率,就像书的目录一样 常见索引数据结构(每碰到一个新数据库,我们需要先关注它的数据模型,这样才能从理论上分析出这个数据库的适用场景) 哈希…...
XQuery 函数
XQuery 1.0、XPath 2.0 以及 XSLT 2.0 共享相同的函数库。 XQuery 函数 XQuery 含有超过 100 个内建的函数。这些函数可用于字符串值、数值、日期以及时间比较、节点和 QName 操作、序列操作、逻辑值等等。您也可在 XQuery 中定义自己的函数。 XQuery 内建函数 XQuery 函数命…...

Elasticsearch的安装及常用操作
文章目录一、Elasticsearch的介绍1、Elasticsearch索引2、Elasticsearch的介绍二、Elasticsearch的安装1、安装ES服务2、安装kibana3、Docker安装ES4、Docker安装Kibana三、ES的常用操作1、索引操作2、文档操作3、域的属性3.1 index3.2 type3.3 store总结一、Elasticsearch的介…...

网络安全应急响应服务方案怎么写?包含哪些阶段?一文带你了解!
文章目录一、服务范围及流程1.1 服务范围1.2 服务流程及内容二、准备阶段2.1 负责人准备内容2.2 技术人员准备内容(一)服务需求界定(二)主机和网络设备安全初始化快照和备份2.3市场人员准备内容(1)预防和预…...
11、事务原理和实战,MVCC
事务原理和实战 1. 认识事务2. 事务控制语句2.1 开启事务2.2 事务提交2.3 事务回滚3. 事务的实现方式3.1 原子性3.2 一致性3.3 隔离性3.3 持久性4purge thread线程5事务统计QPS与TPS5.1 QPS5.2 TPS6. 事务隔离级别6.1 隔离级别6.2 查看隔离级别6.3 设置隔离级别6.4 不同隔离级别…...

Robust Self-Augmentation for Named Entity Recognition with Meta Reweighting
摘要 近年来,自我增强成为在低资源场景下提升命名实体识别性能的研究热点。Token substitution and mixup (token替换和表征混合)是两种有效提升NER性能的自增强方法。明显,自增强方法得到的增强数据可能由潜在的噪声。先前的研究…...

Java基础-xml
1.xml 1.1概述 万维网联盟(W3C) 万维网联盟(W3C)创建于1994年,又称W3C理事会。1994年10月在麻省理工学院计算机科学实验室成立。 建立者: Tim Berners-Lee (蒂姆伯纳斯李)。 是Web技术领域最具权威和影响力的国际中立性技术标准机构。 到目前为止&#…...
TCP的Nagle算法和delayed ack---延时发送和延时应答与稍带应答选项
本文目录提高TCP的网络利用率的二个思考解决方案:Nagle算法和delayed ack(延时发送和延时应答与稍带应答选项)Nagle算法和delayed ack算法同时启动可能会导致的问题提高TCP的网络利用率的二个思考 我们都知道,TCP是一个基于字节流…...

智能拣配单解决方案
电子货架标签系统(ESLs),是一种放置在货架上、可替代传统纸质价格标签的电子显示装置, 每一个电子货架标签通过有线或者无线网络与商场计算机数据库相连, 并将最新的商品价格通过电子货架标签上的屏显示出来。 电子…...
如何防御入侵服务器
根据中华人民共和国刑法: 第二百八十六条违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行,后果严重的,处五年以下有期徒刑或者拘役;后果特别严重的ÿ…...

[软件工程导论(第六版)]第4章 形式化说明技术(课后习题详解)
文章目录1. 举例对比形式化方法和欠形式化方法的优缺点。2. 在什么情况下应该使用形式化说明技术?使用形式化说明技术时应遵守哪些准则?3. 一个浮点二进制数的构成是:一个可选的符号(+或-)&…...

Premiere基础操作
一:设置缓存二:ctrI导入素材三:导入图像序列四:打开吸附。打开吸附后素材会对齐。五:按~键可以全屏窗口。六:向前选择轨道工具。在时间线上点击,向前选中时间线上素材。向后选择轨道工具&#x…...

Prometheus监控案例-tomcat、mysql、redis、haproxy、nginx
监控tomcat tomcat自身并不能提供监控指标数据,需要借助第三方exporter实现:https://github.com/nlighten/tomcat_exporter 构建镜像 基于tomcat官方镜像,重新制作一个镜像,将tomcat-exporter和tomcat整合到一起。Ddockerfile如…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...

MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...

ui框架-文件列表展示
ui框架-文件列表展示 介绍 UI框架的文件列表展示组件,可以展示文件夹,支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项,适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...