cc-product-waterfall仿天猫、淘宝购物车店铺商品列表组件

cc-product-waterfall仿天猫、淘宝购物车店铺商品列表组件

引言

在电商应用中,购物车体验的优化对于提升用户满意度和转化率至关重要。在本文中,我们将深入探讨如何使用cc-product-waterfall组件,结合uni-number-box和xg-widget,来构建一个仿天猫、淘宝的购物车店铺商品列表。同时,我们将详细解析相关的事件处理函数,以实现如商品过滤、店铺勾选、商品勾选、数量改变以及全选等功能。

组件介绍

cc-product-waterfall

cc-product-waterfall是一个强大的商品列表组件,支持瀑布流布局,非常适合用于展示大量商品。

uni-number-box

uni-number-box是一个数字输入框组件,用户可以通过它方便地修改商品数量。

xg-widget

xg-widget是一套通用的UI组件库,可以帮助我们快速构建出复杂且交互性强的用户界面。

购物车店铺商品列表实现

步骤1:引入必要的组件

首先,确保你的项目中已经引入了cc-product-waterfall、uni-number-box和xg-widget等组件。具体的引入方法可能会根据你使用的框架或库有所不同。

步骤2:构建基本布局

使用cc-product-waterfall构建商品列表,uni-number-box用于商品数量的输入,xg-widget中的checkbox组件用于实现店铺和商品的勾选功能。

步骤3:添加交互功能

通过事件处理函数来实现各种交互功能,包括商品过滤、店铺勾选、商品勾选、数量改变以及全选等。

事件处理详解

过滤选择的商品和未选择的商品

filterCheckedProductfilterUncheckedProduct方法分别用于过滤出已选择和未选择的商品。这两个方法都接受一个商品列表作为参数,然后使用数组的filter方法根据商品的checked属性进行过滤。

示例代码:
使用方法
 
引入uni-number-box xg-widget组件

事件处理如下:
// 过滤选择的商品
filterCheckedProduct(products) {
return products.filter(item => item.checked);
},
// 过滤未选择的商品
filterUncheckedProduct(products) {
return products.filter(item => !item.checked);
},
// 店铺勾选
onShopCheckboxTap(shop) {
shop.checked = !shop.checked;

shop.products.forEach(product => {
product.checked = shop.checked;
});
},
// 商品勾选
onProductCheckboxTap(product) {
product.checked = !product.checked
},
// 数量改变
onNumberBoxChange(product, e) {
product.count = e;
},
// 全选
onCheckAllTap() {
const checked = !this.allChecked;
this.shops.forEach(shop => {
shop.products.forEach(product => {
product.checked = checked;
})
})
}
HTML代码实现部分

<template>
    <view>
        <!-- 空购物车 -->
        <view v-if="isEmptyCart"
            class="bg-color-white border-bottom-left-radius-xl border-bottom-right-radius-xl padding-lg">
            <view class="row-center-center">
                <image class="img-size-xl" src="/static/cart/empty-cart.png" mode="aspectFit"></image>
                <text class="font-size-lg text-color-greyblack">购物车是空的</text>
            </view>
            <view class="row-center-center">
                <text class="empty-button">逛逛秒杀</text>
                <text class="empty-button">看看关注</text>
            </view>
        </view>

        <!-- 非空购物车 -->
        <view v-if="!isEmptyCart">
            <view v-for="(shop, shopIndex) of cartShops" :key="shopIndex"
                class="padding-lg margin-bottom-lg bg-color-white border-radius-xl">
                <!-- 店铺购物车商品 -->
                <!-- 店铺标题 -->
                <view class="" @tap="onShopCheckboxTap(shop)">
                    <label class="row-between-center">
                        <view class="row-center-center">
                            <checkbox class="shop-checkbox" :checked="shop.checked" />
                            <image class="img-size-base border-radius-circle" :src="shop.logo" mode="aspectFit"></image>
                            <text class="font-size-lg">{{shop.name}}</text>
                        </view>
                        <!-- <view class=""></view> -->
                    </label>
                </view>

                <!-- 店铺产品列表 -->
                <view class="row-between-start margin-top-base" v-for="(product, productIndex) of shop.products"
                    :key="productIndex">
                    <view class="product-checkbox" @tap="onProductCheckboxTap(product)">
                        <checkbox :checked="product.checked" />
                    </view>

                    <image class="border-radius-lg product-image" :src="product.image" mode=""></image>
                    <view class="flex-1 column-center-stretch padding-left-lg">
                        <text class="lines-2 font-size-base">{{product.title}}</text>
                        <view class="row-start-center margin-v-side-base">
                            <view
                                class="row-center-center bg-color-grey border-radius-rect-circle padding-side-base padding-v-side-xs">
                                <text v-for="(property, propertyIndex) of product.sku" :key="propertyIndex"
                                    class="font-size-sm">{{property}},</text>
                            </view>
                        </view>

                        <view class="row-between-center">
                            <xg-money camel :size="UNI_FONT_SIZE_XL" :money="product.price"></xg-money>

                            <view class="number-box">
                                <uni-number-box :min="1" :value="product.count"
                                    @change="onNumberBoxChange(product, $event)"></uni-number-box>
                            </view>
                        </view>
                    </view>
                </view>

            </view>
        </view>

        <view class="order-amount-placeholder"></view>
        <view class="row-between-center bg-color-white padding-side-lg order-amount">
            <view class="row-center-center">
                <view class="product-checkbox" @tap="onCheckAllTap">
                    <checkbox :checked="allChecked" />
                </view>
                <text class="font-size-base">全选</text>
                <text class="font-size-lg margin-left-lg">合计:</text>
                <text class="font-size-lg font-weight-bold">¥{{totalAmount.toFixed(2)}}</text>
            </view>

            <view class="bg-color-red border-radius-rect-circle padding-side-lg padding-v-side-base">
                <text class="font-size-lg text-color-white">去结算({{totalCount}})</text>
            </view>
        </view>
    </view>
</template>

<script>
    // 获取购物车数据来源
    import data from '@/data/cart/cart';

    import mixin from '@/common/mixin';

    const customData = {
        page: 0
    }

    export default {
        mixins: [mixin],
        data() {
            return {
                isEmptyCart: false,
                loadMoreStatus: 'more',

                shops: [],

            };
        },

        computed: {
            // 全选事件
            allChecked() {
                return this.cartShops.filter(item => item.checked).length === this.cartShops.length;
            },

            // 购物车店铺数据
            cartShops() {
                this.shops.forEach(shop => {
                    const uncheckedProducts = this.filterUncheckedProduct(shop.products);

                    shop.checked = (uncheckedProducts.length === 0);
                })

                return this.shops;
            },

            // 计算数量
            totalCount() {
                let count = 0;

                this.cartShops.forEach(shop => {
                    this.filterCheckedProduct(shop.products).forEach(product => {
                        count += parseInt(product.count);
                    })
                })

                return count;
            },
            // 计算金额
            totalAmount() {
                let amount = 0;

                this.cartShops.forEach(shop => {
                    this.filterCheckedProduct(shop.products).forEach(product => {
                        amount += Number(product.price * product.count)
                    })
                })

                return amount;
            }
        },

        async created() {
            this.loadMoreStatus = 'loading';

            // 获取商铺数据
            const shopPromise = data.shops();

            this.shops = await shopPromise;

        },

        methods: {
            // 过滤选择的商品
            filterCheckedProduct(products) {
                return products.filter(item => item.checked);
            },
            // 过滤未选择的商品
            filterUncheckedProduct(products) {
                return products.filter(item => !item.checked);
            },
            // 店铺勾选
            onShopCheckboxTap(shop) {
                shop.checked = !shop.checked;

                shop.products.forEach(product => {
                    product.checked = shop.checked;
                });
            },
            // 商品勾选
            onProductCheckboxTap(product) {
                product.checked = !product.checked
            },
            // 数量改变
            onNumberBoxChange(product, e) {
                product.count = e;
            },
            // 全选
            onCheckAllTap() {
                const checked = !this.allChecked;
                this.shops.forEach(shop => {
                    shop.products.forEach(product => {
                        product.checked = checked;
                    })
                })
            }

        },
    }
</script>

<style lang="scss" scoped>
    .empty-button {
        @include border(1px solid);

        font-size: $uni-font-size-lg;
        border-radius: $uni-border-radius-rect-circle;
        margin: 0 $uni-spacing-col-xl;
        padding: $uni-spacing-row-sm $uni-spacing-col-xl;
    }

    $order-amount-height: 100rpx;

    .product-list {
        /* #ifdef APP-NVUE */

        @include position(fixed, 0 0 $order-amount-height 0);
        /* #endif */

        // width: 500rpx;
    }

    .shop-checkbox {
        transform: scale(0.8);
    }

    .product-checkbox {
        transform: scale(0.75);
    }

    .product-image {
        width: 200rpx;
        height: 200rpx;
    }

    .number-box {
        transform-origin: 100% 50%;
        transform: scale(0.75);
    }

    .order-amount-placeholder {
        height: $order-amount-height;
    }

    .order-amount {
        /* #ifndef APP-NVUE */
        @include position(fixed, none 0 var(--window-bottom) 0);
        /* #endif */
        /* #ifdef APP-NVUE */
        @include position(fixed, none 0 0 0);
        /* #endif */

        height: $order-amount-height;

        /* #ifndef APP-NVUE */
        z-index: 10000;
        /* #endif */
    }
</style>

店铺勾选和商品勾选功能实现

当用户点击店铺或商品的勾选框时,我们需要更新对应的checked状态。onShopCheckboxTap方法用于处理店铺的勾选事件,它会更新店铺及其所有商品的checked状态。onProductCheckboxTap方法用于处理商品的勾选事件,只会更新当前商品的checked状态。这两个方法都使用了JavaScript的逻辑非操作符来实现checked状态的切换。当用户点击全选按钮时,onCheckAllTap方法将会被调用。这个方法会检查当前的全选状态,然后遍历所有的店铺和商品,将它们的checked状态设置为相反的值。这样就可以实现一键全选或全不选的功能

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

d848d5658a07453c843277846948c608.png

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

『Nginx安全访问控制』利用Nginx实现账号密码认证登录的最佳实践

&#x1f4e3;读完这篇文章里你能收获到 如何创建用户账号和密码文件&#xff0c;并生成加密密码配置Nginx的认证模块&#xff0c;实现基于账号密码的登录验证 文章目录 一、创建账号密码文件1. 安装htpasswd工具1.1 CentOS1.2 Ubuntu 二、配置Nginx三、重启Nginx 在Web应用程…

Linux驱动开发学习笔记1《字符设备驱动开发》

目录 一、字符设备驱动简介 二、chrdevbase 字符设备驱动开发实验 1.创建驱动程序的目录 2.创建vscode工程 3.编写实验程序 4.编译驱动程序和测试APP代码 &#xff08;1&#xff09;加载驱动模块 &#xff08;2&#xff09;创建设备节点文件 &#xff08;3&#xff…

【开源】前后端分离的在线考试系统,支持多种部署方式

在线考试系统 https://download.csdn.net/download/mo3408/88593116 在线考试系统是一种利用网络技术&#xff0c;实现在线出题、答题、阅卷、成绩查询等一系列考试活动的系统。它不受地理位置限制&#xff0c;可以实现远程考试&#xff0c;大大提高了考试的效率和便利性。此…

HBASE命令行查看中文字符

问题记录 中文显示的是编码字符不方便查看value\xE5\xB8\xB8\xE5\xAE\x89\xE5\xAE\x891修改前中文显示&#xff1a; 解决方法 1、列族 : 列名 : toString ’2、列族 : 列名 : c(org.apache.hadoop.hbase.util.Bytes).toString ’ scan karry:student,{COLUMNS > [info:…

C-语言每日刷题

目录 [蓝桥杯 2015 省 A] 饮料换购 题目描述 输入格式 输出格式 输入输出样例 # [蓝桥杯 2023 省 A] 平方差 题目描述 输入格式 输出格式 输入输出样例 说明/提示 【样例说明】 [NOIP2001 普及组] 数的计算 题目描述 输入格式 输出格式 输入输出样例 说明/提示 样例 1 解释 数据…

SQL自学通之简介

目录 一、SQL 简史 二、数据库简史 1、Dr. Codds 对关系型数据库系统的十二条规则 2、设计数据库的结构 3、数据库的前景 4、对于什么是客户机/服务器型电脑系统 BernardH.Boar的定义如下&#xff1a; 5、交互式语言 6、易于实现 7、SQL 总览 三、流行的 SQL 开发工具…

python初始化矩阵相关

做算法题经常需要初始化一个二维的dp数组 下面两种方法是最常用的 matrix [[0]*n]*n matrix [[0]*n for _ in range(n)]以前经常混用也没发现什么问题&#xff0c;直到昨天debug的时候发现第一种初始化之后对矩阵进行赋值时混乱的&#xff0c;比如matrix[0][1]2会导致所有行…

[Linux ] sed文本处理和免交互

一、sed 1.1 sed是什么 sed 是一种流编辑器&#xff08;stream editor&#xff09;&#xff0c;用于对文本数据进行文本转换和处理。它通常被用于在命令行中执行文本编辑任务&#xff0c;可以对输入的文本进行搜索、替换、删除等操作&#xff0c;并将结果输出。sed 是一个非交…

Linux脚本awk命令

目录 一. awk命令简介 1. awk版本 2. awk与vim的区别 3. awk与sed的区别 4. awk工作原理 5. awk格式 6. awk常用选项 二. awk基础用法 1. awk基础用法 2. BEGIN和END语句块 3. 指定分隔符 4. 首尾关键字 三. awk内置变量 1. FS变量 2. OFS变量 3. RS变量 4. NF…

线程安全的问题以及解决方案

线程安全 线程安全的定义 线程安全:某个代码无论是在单线程上运行还是在多线程上运行,都不会产生bug. 线程不安全:单线程上运行正常,多线程上运行会产生bug. 观察线程不安全 看看下面的代码: public class ThreadTest1 {public static int count 0;public static void main…

Windows驱动中数字签名认证(使用 ci.dll)

1.背景 对于常规应用程序来说&#xff0c;在应用层可以使用 WinVerifyTrust, 在驱动层使用常规的 API无法使用&#xff0c;自己分析数据又太麻烦。 但在内核中 ci.dll 包装了数据签名验证相关的功能&#xff0c;我们可以使用该 dll 来实现我们的数字签名验证。 详细的分析见《内…

《异常检测——从经典算法到深度学习》24 用于单变量时间序列异常检测的端到端基准套件

《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: …

面试题:千万量级数据中查询 10W 量级的数据有什么方案?

文章目录 前言初版设计方案整体方案设计为&#xff1a;技术方案如下&#xff1a;CK 分页查询使用 ES Scroll Scan 优化深翻页耗时数据 ESHbase 组合查询方案ES 查询的两个阶段组合使用 Hbase RediSearchRedisJSON 优化方案RediSearch 性能数据RedisJSON 性能数据 总结 前言 在…

C++跨目录include问题

不同文件夹下使用预处理器指示符#include 使用举例 假设我们有如下一个工程&#xff0c;其中包含了几个源代码和头文件&#xff0c;其中main.cpp是主源代码文件&#xff0c;里面含有main函数&#xff1a; 在foldder main中包含&#xff1a;func4.hpp&#xff0c;func4.cpp&am…

MIT线性代数笔记-第21讲-特征值,特征向量

目录 21.特征值&#xff0c;特征向量打赏 21.特征值&#xff0c;特征向量 对于一个方阵 A A A&#xff0c;若 A x ⃗ λ x ⃗ A \vec{x} \lambda \vec{x} Ax λx &#xff0c;即 A x ⃗ A \vec{x} Ax 平行于 x ⃗ \vec{x} x &#xff0c;那么 λ \lambda λ是 A A A的特征值…

100W用户、8000W流量在线贺卡应用架构如何优化?

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容&#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作…

FL Studio2024水果编曲软件21.2.0中文版本下载更新

FL Studio2024是功能强大的音乐制作解决方案&#xff0c;使用旨在为用户提供一个友好完整的音乐创建环境&#xff0c;让您能够轻松创建、管理、编辑、混合具有专业品质的音乐&#xff0c;一切的一切都集中在一个软件中&#xff0c;只要您想&#xff0c;只要您需要&#xff0c;它…

Leetcode—409.最长回文串【简单】

2023每日刷题&#xff08;四十八&#xff09; Leetcode—409.最长回文串 强烈吐槽&#xff01;&#xff01;&#xff01; 非常不理解&#xff0c;同样的代码&#xff0c;为什么C跑不了C就跑得了&#xff0c;力扣编译器是对C语言有歧视吗&#xff1f;&#xff1f;&#xff1f;…

【C++练级之路】【Lv.1】C++,启动!(命名空间,缺省参数,函数重载,引用,内联函数,auto,范围for,nullptr)

目录 引言入门须知一、命名空间1.1 作用域限定符1.2 命名空间的意义1.3 命名空间的定义1.4 命名空间的使用 二、C输入&输出2.1 cout输出2.2 cin输入2.3 std命名空间的使用惯例 三、缺省参数3.1 缺省参数概念3.2 缺省参数分类 四、函数重载4.1 函数重载概念4.2 函数重载分类…

6-63.圆类的定义与使用(拷贝构造函数)

本题要求完成一个圆类的定义&#xff0c;设计适当的函数&#xff1a;包括构造函数、拷贝构造函数以及析构函数&#xff0c;从而可以通过测试程序输出样例 在这里给出一组输入。例如&#xff1a; 5 输出样例&#xff1a; 在这里给出相应的输出。例如&#xff1a; Constructo…
最新文章