仿京东淘宝商品列表筛选组件:实现一个高效的侧边栏弹框筛选功能

news2025/6/13 20:08:24

仿京东淘宝商品列表筛选组件:实现一个高效的侧边栏弹框筛选功能

图片

图片

一、引言

随着电子商务的快速发展,用户体验成为了竞争的关键因素。在众多的电商网站中,如京东和淘宝,商品列表筛选功能为用户提供了便捷的途径来找到心仪的商品。本文将详细介绍如何使用cc-widget、uni-icons和xg-list组件来仿制京东淘宝的商品列表筛选组件,并实现一个高效的侧边栏弹框筛选功能。

二、需求分析

我们的目标是创建一个仿京东淘宝的商品列表筛选组件,具有以下功能:

  1. 点击筛选标签时,能够切换到相应的筛选选项。

  2. 当点击“价格”标签时,显示价格图标状态;点击其他标签时,重置价格图标状态。

  3. 当点击“排序”标签时,显示排序选项;点击其他标签时,隐藏排序选项。

  4. 当点击“筛选”标签时,弹出一个侧边栏筛选弹框。

  5. 点击综合推荐排序方式时,能够设置当前排序选项,并隐藏排序选项。

  6. 点击筛选确定按钮时,能够触发一个事件来处理筛选结果。

三、技术实现

为了实现上述功能,我们需要使用Vue.js框架和一些UI组件库。这里我们选用cc-widget、uni-icons和xg-list组件来实现。

  1. 引入必要的组件库

在项目中引入cc-widget、uni-icons和xg-list组件库,确保能够正确使用这些组件。

  1. 编写HTML结构

根据需求,编写筛选组件的HTML结构。使用cc-widget、uni-icons和xg-list组件来构建基本的筛选框架。

  1. 实现事件处理逻辑

根据需求分析中的事件处理要求,编写相应的方法来处理点击事件。使用Vue.js的事件绑定机制来监听点击事件,并调用相应的方法来处理逻辑。

四、代码实现

使用方法
引入cc-widget uni-icons xg-list组件     

事件处理如下:
// 筛选点击
            onTabTitleTap(index) {
                console.log("index = " + index);
                this.setCurrentTabTitleIndex(index);

                if ('price' !== index) {
                    this.resetPriceIconStatus();
                }

                if ('sort' !== index) {
                    this.hiddenSortOptions();
                }

                if ('sort' === index) {
                    this.toggleSortOptions();

                    return;
                }

                if ('volume' === index) {

                    return;
                }

                if ('price' === index) {
                    this.togglePriceIconStatus();

                    return;
                }

                if ('filter' === index) {
                    this.$refs['filter-popup'].open();
                    return;
                }
            },

            // 综合推荐排列方式点击
            onSortOptionTap(index) {
                this.setCurrentSortOptionIndex(index);
                this.hiddenSortOptions();

                console.log("综合推荐排列方式 = " + index);
            },

            // 筛选确定
            onFilterConfirm(e) {
                console.log("filter确定 = " + JSON.stringify(e));
            }
<template>
    <view class="">
        <!-- #ifdef MP-WEIXIN -->
        <uni-nav-bar fixed status-bar left-icon="back" @clickLeft="onBackPressTap">
            <view slot="left" class="nav-bar-search-bar" :style="{width: searchBarWidth + 'px'}">
                <tpl-search-bar cancelButton="none" :radius="10000" @confirm="" @input="" />
            </view>
        </uni-nav-bar>
        <view class="status-bar-placeholder"></view>
        <!-- #endif -->

        <view class="tab-title-section-placeholder"></view>
        <view class="tab-title-section">
            <!-- #ifdef MP-WEIXIN -->
            <xg-status-bar></xg-status-bar>
            <!-- #endif -->
            <view class="position-relative ">
                <view class="row-center-center bg-color-white  tab-title-list-wrap">
                    <view class="flex-1 row-between-stretch padding-side-lg  tab-title-list">
                        <view class="row-center-stretch" @tap="onTabTitleTap('sort')">
                            <view class="tab-title-left">
                                <view class="tab-title-left-text">
                                    <text class="font-size-lg">{{currentSortOptionTitle}}</text>
                                </view>
                                <view v-if="currentTabTitleIndex === 'sort'" class="title-line"></view>
                            </view>

                            <view class="tab-title-right-icon">
                                <uni-icons :type="showSortOptions ? 'arrowup' : 'arrowdown'" :size="12"></uni-icons>
                            </view>
                        </view>
                        <view class="row-center-stretch" @tap="onTabTitleTap('volume')">
                            <view class="tab-title-left">
                                <view class="tab-title-left-text">
                                    <text class="font-size-lg">销量</text>
                                </view>
                                <view v-if="currentTabTitleIndex === 'volume'" class="title-line"></view>
                            </view>
                        </view>
                        <view class="row-center-stretch" @tap="onTabTitleTap('price')">
                            <view class="tab-title-left">
                                <view class="tab-title-left-text">
                                    <text class="font-size-lg">价格</text>
                                </view>
                                <view v-if="currentTabTitleIndex === 'price'" class="title-line"></view>
                            </view>
                            <view class="column-center-center tab-title-right-icon">
                                <view class="column-center-center" v-if="priceIconStatus === 'all'">
                                    <uni-icons class="" v-if="priceIconStatus === 'all' || priceIconStatus === 'up'"
                                        type="arrowup" :size="12"></uni-icons>
                                    <uni-icons class="" v-if="priceIconStatus === 'all' || priceIconStatus === 'down'"
                                        type="arrowdown" :size="12"></uni-icons>
                                </view>
                                <view v-else>
                                    <uni-icons v-if="priceIconStatus === 'up'" type="arrowup" :size="12"></uni-icons>
                                    <uni-icons v-if="priceIconStatus === 'down'" type="arrowdown"
                                        :size="12"></uni-icons>
                                </view>
                            </view>
                        </view>
                        <view class="row-center-stretch" @tap="onTabTitleTap('filter')">
                            <view class="tab-title-left">
                                <view class="tab-title-left-text">
                                    <text class="font-size-lg">筛选</text>
                                </view>
                                <view v-if="currentTabTitleIndex === 'filter'" class="title-line"></view>
                            </view>
                        </view>

                        <!-- #ifdef MP-WEIXIN -->
                        <view class="" @tap="onWaterfallSwitchTap">
                            <image class="img-size-base"
                                :src="!waterfall ? '/static/product/waterfall.png' : '/static/product/list.png'"
                                mode=""></image>
                        </view>
                        <!-- #endif -->
                    </view>

                </view>

                <view v-if="showTabTitleMask" :style="{height: screenHeight + 'px'}" class="tab-title-mask"
                    @tap="onTabMaskTap"></view>
                <view v-if="showSortOptions"
                    class="bg-color-grey border-bottom-left-radius-xl border-bottom-right-radius-xl padding-lg sort-options-section">
                    <view class="row-start-center sort-option" v-for="(sortOption, sortOptionIndex) of sortOptions"
                        :key="sortOptionIndex" @tap="onSortOptionTap(sortOptionIndex)">
                        <uni-icons v-if="sortOptionIndex === currentSortOptionIndex" type="checkmarkempty" :size="20"
                            :color="UNI_COLOR_RED"></uni-icons>
                        <text class="font-size-lg"
                            :class="{'font-weight-bold': sortOptionIndex === currentSortOptionIndex}">{{sortOption.desc}}</text>
                    </view>

                </view>

            </view>

        </view>

        <com-product-list :waterfall="waterfall" :products="products"></com-product-list>

        <com-drawer ref="filter-popup" mode="right" :width="toPx('600rpx')">
            <com-filter class="filter-popup-content" :serviceOptions="serviceOptions" :brandOptions="brandOptions"
                :specificationOptions="specificationOptions" @confirm="onFilterConfirm"></com-filter>
        </com-drawer>
    </view>
</template>

<script>
    import data from '@/data/product/list';
    import config from './list/config.js';

    import mixin from '@/common/mixin';

    import comProductList from './list/com-product-list';
    import comFilter from './list/com-filter';
    import comDrawer from './list/com-drawer';

    export default {
        mixins: [mixin, config],
        components: {
            comProductList,
            comFilter,
            comDrawer
        },
        data() {
            return {
                serviceOptions: [],
                brandOptions: [],
                specificationOptions: [],

                products: []
            }
        },

        async created() {
            const productsPromise = data.products();
            const serviceOptionsPromise = data.serviceOptions();
            const brandOptionsPromise = data.brandOptions();
            const specificationOptionsPromise = data.specificationOptions();

            this.specificationOptions = await specificationOptionsPromise;
            this.brandOptions = await brandOptionsPromise;
            this.serviceOptions = await serviceOptionsPromise;
            this.products = await productsPromise;
        },

        onNavigationBarButtonTap(e) {
            this.toggleWaterfall();
        },

        methods: {
            // #ifdef MP-WEIXIN
            onBackPressTap() {
                uni.navigateBack({
                    delta: 1
                })
            },
            onWaterfallSwitchTap() {
                this.toggleWaterfall();
            },
            // #endif

            onTabMaskTap() {
                this.hiddenSortOptions();
            },

            // 筛选点击
            onTabTitleTap(index) {
                console.log("index = " + index);
                this.setCurrentTabTitleIndex(index);

                if ('price' !== index) {
                    this.resetPriceIconStatus();
                }

                if ('sort' !== index) {
                    this.hiddenSortOptions();
                }

                if ('sort' === index) {
                    this.toggleSortOptions();

                    return;
                }

                if ('volume' === index) {

                    return;
                }

                if ('price' === index) {
                    this.togglePriceIconStatus();

                    return;
                }

                if ('filter' === index) {
                    this.$refs['filter-popup'].open();
                    return;
                }
            },

            // 综合推荐排列方式点击
            onSortOptionTap(index) {
                this.setCurrentSortOptionIndex(index);
                this.hiddenSortOptions();

                console.log("综合推荐排列方式 = " + index);
            },

            // 筛选确定
            onFilterConfirm(e) {
                console.log("filter确定 = " + JSON.stringify(e));
            }
        },
    }


<style lang="scss" scoped>
    .title-line {
        width: 50rpx;
        height: 8rpx;
        background-color: $uni-color-red;
    }

    /* #ifdef MP-WEIXIN */
    .status-bar-placeholder {
        @include position(fixed, 0 0 none 0);

        height: var(--status-bar-height);

        z-index: 10000;
        background-color: $uni-color-white;
    }

    .nav-bar-search-bar {
        // width: 430rpx;
    }

    /* #endif */

    $tab-title-section-height: 100rpx;

    $tab-title-item-top-section-height: 50rpx;

    .tab-title-section-placeholder {
        height: $tab-title-section-height;
    }

    .tab-title-section {
        @include position(fixed, 0 0 none 0);
        /* #ifdef MP-WEIXIN */
        top: 44px;
        /* #endif */
        /* #ifdef H5 */
        top: var(--window-top);
        /* #endif */

        /* #ifndef APP-NVUE */
        z-index: 1;
        /* #endif */
    }

    .tab-title-list-wrap {
        height: $tab-title-section-height;
    }

    .tab-title-list {
        height: $tab-title-item-top-section-height + 20rpx;
    }

    .tab-title-left {
        @include flex-layout(column, space-between, center);
    }

    .tab-title-left-text {
        height: $tab-title-item-top-section-height;
        @include flex-layout(column, center, center);
    }

    .tab-title-right-icon {
        height: $tab-title-item-top-section-height;
        @include flex-layout(column, center, center);
    }

    .tab-title-mask {
        background-color: rgba($color: #000000, $alpha: 0.8);
    }

    .sort-options-section {
        @include position(absolute, $tab-title-section-height 0 none 0);
    }

    .sort-option {
        height: 60rpx;
    }

    .filter-popup-content {
        @include position(absolute, 0 0 0 0);

        /* #ifdef MP-WEIXIN */
        top: var(--status-bar-height);
        /* #endif */
    }
</style>

五、测试与验证

在代码实现完成后,我们需要进行测试与验证来确保功能的正确性。可以使用自动化测试工具或手动测试来验证每个功能点的正确性。例如,点击不同的筛选标签时,是否能够正确切换到相应的筛选选项;点击排序标签时,是否能够正确显示和隐藏排序选项;点击筛选确定按钮时,是否能够正确触发事件处理逻辑等。通过详细的测试与验证,可以确保我们的仿京东淘宝商品列表筛选组件的功能正确且健壮。

六、总结与展望

本文详细介绍了如何使用cc-widget、uni-icons和xg-list组件来仿制京东淘宝的商品列表筛选组件,并实现了一个高效的侧边栏弹框筛选功能。通过需求分析和技术实现的过程,我们可以了解到如何使用Vue.js框架和一些UI组件库来实现复杂的交互功能。同时,我们也进行了测试与验证来确保功能的正确性。在未来的工作中,我们可以进一步优化代码结构和性能,提高用户体验和系统的可扩展性。

 阅读全文下载完整组件代码请关注微信公众号: 前端组件开发

d848d5658a07453c843277846948c608.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1277993.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

策略模式与简单工厂模式:终结if-else混乱,让代码更清爽

阅读建议 嗨&#xff0c;伙计&#xff01;刷到这篇文章咱们就是有缘人&#xff0c;在阅读这篇文章前我有一些建议&#xff1a; 本篇文章大概4500多字&#xff0c;预计阅读时间长需要5分钟。本篇文章的实战性、理论性较强&#xff0c;是一篇质量分数较高的技术干货文章&#x…

STM32-GPIO

一、GPIO简介 GPIO&#xff08;General Purpose Input Output&#xff09;通用输入输出口 可配置8种输入输出模式 引脚电平&#xff1a;0V~3.3V&#xff0c;部分引脚可容忍5V 输出模式下&#xff1a;可控制端口输出高低电平&#xff0c;用以驱动LED、控制蜂鸣器、模拟通信协议输…

Windows11系统下MemoryCompression导致内存占用率过高

. # &#x1f4d1;前言 本文主要是win11系统下CPU占用率过高如何下降的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日…

java学习part30callabel和线程池方式

140-多线程-线程的创建方式3、4&#xff1a;实现Callable与线程池_哔哩哔哩_bilibili 1.Callable 实现类 使用方式 返回值 2.线程池

[英语学习][5][Word Power Made Easy]的精读与翻译优化

[序言] 今日完成第18页的阅读, 发现大量的翻译错误以及不准确. 需要分两篇文章进行讲解. [英文学习的目标] 提升自身的英语水平, 对日后编程技能的提升有很大帮助. 希望大家这次能学到东西, 同时加入我的社区讨论与交流英语相关的内容. [原著英文与翻译版对照][第18页] Wh…

Lattice-Based Blind Signatures: Short, Efficient, and Round-Optimal

目录 摘要引言 Lattice-Based Blind Signatures: Short, Efficient, and Round-Optimal CCS 2023 摘要 我们提出了一种基于随机预言机启发式和标准格问题&#xff08;环/模块SIS/LWE和NTRU&#xff09;的2轮盲签名协议&#xff0c;签名大小为22KB。该协议是全面优化的&#xf…

Elasticsearch 的使用

一、简介 1.Shard&#xff08;分片&#xff09; 数据分散集群的架构模式&#xff0c;Elasticsearch 将一个 Index&#xff08;索引&#xff09;中的数据切为多个 Shard&#xff08;分片&#xff09;&#xff0c;分布在不同服务器节点上。 默认每个索引会分配5个主分片和1个副本…

HarmonyOS开发工具安装

目录 下载与安装DevEco Studio DevEco Studio下载官网&#xff0c;点击下载 下载完成后&#xff0c;双击下载的“deveco-studio-xxxx.exe” 进入DevEco Studio安装向导 选择安装路径 如下安装选项界面勾选DevEco Studio后&#xff0c;单击“Next” 点击Install 安装完…

【云备份】业务处理

文章目录 1. 业务处理作用功能 2. 代码框架编写构造函数UpLoad ——文件上传请求ListShow —— 展示页面请求处理实现Download —— 下载请求的处理实现断点续传实现 1. 业务处理 作用 业务处理模块是对客户端的业务请求进行处理 功能 1.文件上传请求&#xff1a;备份客户端…

A--Z与a--z的ASCII码的差异

从z到A还有一些字符 应该改为str[i]>A&&str[i]<Z||str[i]>a&&str[i]<z;

什么是革命性技术eBPF?为什么可观测性领域都得用它

公众号「架构成长指南」&#xff0c;专注于生产实践、云原生、分布式系统、大数据技术分享。 如果有一种技术可以监控和采集任何应用信息&#xff0c;支持任何语言&#xff0c;并且应用完全无感知&#xff0c;零侵入&#xff0c;想想是不是很激动&#xff0c;那么这个技术是什么…

基于SpringBoot蜗牛兼职网的设计与实现

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;蜗牛兼职网当然也不能排除在外。蜗牛兼职网是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c…

【Element-ui】Layout与Container组件

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Layout 布局1.1 基础布局1.2 分栏间隔1.3 混合布局1.4 分栏偏移1.5 对齐方式1.6 响应式布局1.7 el-col中的 push和pull 二、Container 布局容器2.1 Contain…

c语言常见面试题(持续更新)

八股文的意义在于&#xff0c;如果你真正理解这些八股&#xff0c;那么你的编程语言才达到了入门级别&#xff0c;如果你不懂&#xff0c;你绝对还没有入门编程语言&#xff0c;也就是说在接下来的工作中&#xff0c;受限于基础的薄弱&#xff0c;你的工作进展会非常的慢&#…

Python函数的高级用法

Python 的函数是“一等公民”&#xff0c;因此函数本身也是一个对象&#xff0c;函数既可用于赋值&#xff0c;也可用作其他函数的参数&#xff0c;还可作为其他函数的返回值。 使用函数变量 Python 的函数也是一种值&#xff1a;所有函数都是 function 对象&#xff0c;这意…

Android 应用资源概览

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、资源类型分组四、配置限定符名称表…

YOLOv3 学习笔记

文章目录 前言一、YOLOv3贡献和改进二、YOLOv3的核心概念2.1 基础理论和工作原理2.2 YOLOv3对比YOLOv1和YOLOv22.2.1 YOLOv12.2.2 YOLOv2/YOLO90002.2.3 YOLOv3 三、YOLOv3的网络架构3.1 Darknet-533.2 残差连接3.3 多尺度预测3.4 锚框3.5 类别预测和对象检测3.6 上采样和特征融…

HarmonyOS应用开发——程序框架UIAbility、启动模式与路由跳转

前言 UIAbility简单来说就是一种包含用户界面的应用组件&#xff0c;用于和用户进行交互。每一个UIAbility实例&#xff0c;对应于一个最近任务列表中的任务。 一个应用可以有一个UIAbility&#xff0c;也可以有多个UIAbility。一个UIAbility可以对应于多个页面&#xff0c;建议…

微服务实战系列之MemCache

前言 书接前文&#xff0c;马不停蹄&#xff0c;博主继续书写Cache的传奇和精彩。 Redis主要用于数据的分布式缓存&#xff0c;通过设置缓存集群&#xff0c;实现数据的快速响应&#xff0c;同时也解决了缓存一致性的困扰。 EhCache主要用于数据的本地缓存&#xff0c;因无法保…

Maxscript到Python转换工具教程

Maxscript到Python转换器教程 Maxscript到Python转换器采用MAXScript程序&#xff0c;将其解析为语法树&#xff0c;然后从语法树中生成等效的Python代码。通过提供python的自动翻译&#xff0c;帮助python程序员理解maxscript示例。 【项目状况】 将正确解析最正确的maxcript…