1.首先,你需要准备一个文件夹,目录内容如下

2.其次,css中创建一个style.css,内容如下

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: Tahoma, Arial, Helvetica, sans-serif;
    font-size: 12px;
    line-height: 1.2;
}

ul {
    list-style: none;
}

.clearfix::after {
    /* 设置添加的内容,空为了让用户看不见。 */
    content: '';
    /* 控制添加的伪元素是块级元素 */
    display: block;
    /* 清除浮动 */
    clear: both;
    /* 为了让用户看不见。 */
    visibility: hidden;
    height: 0;
    font-size: 0;
}

.clearfix {
    /* css hack  星号表示IE7以下的浏览器,主要为了兼容IE6 */
    *zoom: 1;
}

.shop-cart {
    width: 990px;
    margin: 10px auto;
    /* border: 1px solid red; */
    user-select: none;
}

.tabs {
    height: 35px;
}

.tabs .border {
    border-bottom: 2px solid #e6e6e6;
    position: relative;
}

.tabs .border .line {
    display: inline-block;
    width: 123px;
    height: 2px;
    background: #ff4400;
    position: absolute;
    bottom: -2px;
    left: 0;
    /* 缓动函数=》贝塞尔曲线https://cubic-bezier.com/#.17,.67,.83,.67 */
    transition: left .5s ease;
}

.tabs .border .title {
    display: inline-block;
    font-size: 16px;
    font-weight: bold;
    padding: 5px 20px 10px 20px;
    cursor: pointer;
}

.tabs .border .title.active {
    color: #ff4400;
}

.tabs .border .title span {
    font-size: 14px;
    color: #ff4400;
}

.tabs .border .title:not(.last)::after {
    content: "";
    display: inline-block;
    width: 1px;
    height: 12px;
    transform: scale(.5, 1);
    background: #e6e6e6;
    position: relative;
    left: 20px;
}

.lists .header ul {
    height: 50px;
    line-height: 50px;
}

.lists .header ul li {
    float: left;
    color: #3c3c3c;
}

.lists .header ul li:not(.product-info) {
    width: 125px;
}

.lists .header ul li.product-info {
    width: calc(990px - (125px * 5));
}

.lists .shop .shop-info {
    height: 50px;
    line-height: 50px;
}

.lists .shop .shop-info .shop-tip::before {
    content: '';
    display: inline-block;
    width: 16px;
    height: 18px;
    background-image: url(../img/icons.png);
    background-repeat: no-repeat;
    background-position: -20px -125px;
    position: relative;
    top: 3px;
    margin: 0 5px;
}

.lists .shop .shop-info .shop-name {
    color: #3c3c3c;
    text-decoration: none;
}

.lists .shop .shop-info .shop-name:hover {
    text-decoration: underline;
    color: #ff4400;
}

.lists .shop .shop-info .wangwang {
    display: inline-block;
    width: 20px;
    height: 20px;
    text-indent: -10000px;
    overflow: hidden;
    background-image: url(../img/ww.png);
    background-repeat: no-repeat;
    background-size: contain;
    position: relative;
    left: 10px;
    top: 4px;
}

.lists .shop .products {
    border: 1px solid #ccc;
}

.lists .shop .products .item {
    display: flex;
    padding: 20px 10px;
    border-bottom: 1px solid #eee;
}

.lists .shop .products .item .select-logo {
    display: flex;
}

.lists .shop .products .item .select-logo img {
    width: 80px;
    height: 80px;
    margin-left: 10px;
}

.lists .shop .products .item .product-detail {
    width: calc(990px - (125px * 5));
    display: flex;
}

.lists .shop .products .item .product-detail .left {
    width: calc(990px - (125px * 5) - 190px);
    position: relative;
}

.lists .shop .products .item .product-detail .left .product-name {
    text-decoration: none;
    color: #3c3c3c;
    /* https://www.daqianduan.com/6179.html */
    /* 多行加省略号 */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}

.lists .shop .products .item .product-detail .left .product-name:hover {
    text-decoration: underline;
    color: #ff4400;
}

.lists .shop .products .item .product-detail .left .logos {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
}

.lists .shop .products .item .product-detail .left .logos a {
    text-decoration: none;
    overflow: hidden;
    text-indent: -10000px;
    display: inline-block;
    width: 16px;
    height: 16px;
}

.lists .shop .products .item .product-detail .left .logos a.card {
    background-image: url(../img/xcard.png);
    height: 11px;
}

.lists .shop .products .item .product-detail .left .logos a.service {
    background-image: url(../img/flower.png);
}

.lists .shop .products .item .product-detail .left .logos a.order {
    background-image: url(../img/order.png);
}

.lists .shop .products .item .product-detail .left .logos a.seven {
    background-image: url(../img/seven.png);
}

.lists .shop .products .item .product-detail .right {
    width: 190px;
    color: #9c9c9c;
    padding: 0 20px;
}

.lists .shop .products .item>div:not(.product-detail) {
    width: 125px;
}

.lists .shop .products .item .price p {
    margin: 3px 0;
}

.lists .shop .products .item .price p.market-price {
    color: #9c9c9c;
    text-decoration: line-through;
}

.lists .shop .products .item .price p.real-price {
    color: #000;
    font-weight: 700;
}

.lists .shop .products .item .count {
    font-size: 0;
}

.lists .shop .products .item .count span {
    display: inline-block;
    height: 23px;
    line-height: 20px;
    font-size: 14px;
    text-align: center;
}

.lists .shop .products .item .count span.sub, .lists .shop .products .item .count span.add {
    background-color: #f0f0f0;
    color: #000;
    width: 17px;
    border: 1px solid #e5e5e5;
}

.lists .shop .products .item .count span.sub:hover, .lists .shop .products .item .count span.add:hover {
    color: #ff4400;
    border-color: #ff4400;
}

.lists .shop .products .item .count span.input {
    border: 1px solid #aaa;
}

.lists .shop .products .item .count span.input input {
    width: 40px;
    height: 21px;
    text-align: center;
    border: none;
}

.lists .shop .products .item .amount {
    color: #ff4400;
    font-weight: bold;
    font-size: 14px;
}

.lists .shop .products .item .delete a {
    color: #3c3c3c;
    text-decoration: none;
}

.lists .shop .products .item .delete a:hover {
    text-decoration: underline;
    color: #ff4400;
}

.operate {
    height: 50px;
    background-color: #e5e5e5;
    margin-top: 20px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: #3c3c3c;
    position: sticky;
    bottom: 0;
    left: 0;
}

.operate .left {
    padding-left: 10px;
}

.operate .left a {
    text-decoration: none;
    color: #3c3c3c;
    margin-left: 30px;
}

.operate .left a:hover {
    text-decoration: underline;
    color: #ff4400;
}

.operate .right {
    display: flex;
    justify-content: end;
    align-items: center;
}

.operate .right .amount {
    margin-left: 40px;
}

.operate .right .selected-count, .operate .right .sum {
    color: #ff4400;
    font-size: 18px;
    font-weight: 600;
    margin: 0 5px;
}

.operate .right a {
    height: 50px;
    line-height: 50px;
    width: 120px;
    background-color: #b0b0b0;
    text-align: center;
    text-decoration: none;
    color: #fff;
    font-size: 20px;
}

.operate .right a.active {
    background-color: #ff4400;
}

.operate .right a.active:hover {
    background-color: #f22d00;
}

.even{
    background-color: yellow;
}
.even1{
    background-color: white;
}

.ckb{
    width: 1.1rem;
    height: 1.1rem;
    border-radius: 50%;
    border: 1px solid #b8b4b4;
    display: inline-block;
    cursor: pointer;
    vertical-align: text-bottom;
}

.ckb_s{
    width: 1.1rem;
    height: 1.1rem;
    border-radius: 50%;
    display: inline-block;
    cursor: pointer;
    background: url(../img/gouico.png) no-repeat 0 0;
    background-size: 1.1rem;
    border: 0;
    vertical-align: text-bottom;
}

.bb{
    color: #9e9b9b;
    /* 如果级别不高,则可以用!improtant */
}
.cc{
    color: #000000;
}

 3.js中创建data.js文件

var shopcarts = [
    {
        // 购物车编号
        cartId: 1,
        // 店铺编号 
        shopId: 2001,
        // 店铺名称
        isChecked:false,
        shopName: "荣耀官方旗舰店",
        products: [
            {
                checked:true,
                // 商品编号
                productId: 1001,
                // 商品名称
                productName: "【64GB限时优惠100元】华为旗下荣耀Play4T手机新品大电池AI摄影",
                // 顶层图片
                topImg: "img/4.jpg",
                // 商品图片
                imgs: [
                    "img/1.jpg",
                    "img/2.jpg",
                    "img/3.jpg",
                    "img/4.jpg",
                ],
                // 是否参加电竞节
                isActivity: true,
                // 是否支持信用卡
                isCard: true,
                // 是否支持七天退货
                isSeven: true,
                // 是否如实描述
                isRealDesc: true,
                isChecked:false,
                // 规格
                spec: `<p>机身颜色:iPhone8 银色4.7英寸</p>
                <p>版本类型:中国大陆</p>
                <p>套餐类型:官方标配</p>
                <p>存储容量:256GB</p>`,
                marketPrice: 2000,
                // 单价
                price: 1199.00,
                // 购买的数量
                count: 0,
                // 金额
                amount: 2398.00
            },
            {
                // 商品编号
                productId: 1002,
                // 商品名称
                productName: "【6+64GB魅海蓝限时低至1199元】华为旗下荣耀手机荣耀9X麒麟",
                // 顶层图片
                topImg: "img/5.jpg",
                // 商品图片
                imgs: [
                    "img/1.jpg",
                    "img/2.jpg",
                    "img/3.jpg",
                    "img/4.jpg",
                ],
                // 是否参加电竞节
                isActivity: true,
                // 是否支持信用卡
                isCard: true,
                // 是否支持七天退货
                isSeven: true,
                // 是否如实描述
                isRealDesc: true,
                isChecked:false,
                // 规格
                spec: `<p>机身颜色:iPhone8 银色4.7英寸</p>
                <p>版本类型:中国大陆</p>
                <p>套餐类型:官方标配</p>
                <p>存储容量:256GB</p>`,
                marketPrice: 2000,
                // 单价
                price: 1199.00,
                // 购买的数量
                count: 0,
                // 金额
                amount: 2398.00
            }
        ]
    },
    {
        // 购物车编号
        cartId: 2,
        // 店铺编号 
        shopId: 2002,
        // 店铺名称
        isChecked:false,
        shopName: "罗蒙派大星专卖店",
        products: [
            {
                // 商品编号
                productId: 1003,
                // 商品名称
                productName: "罗蒙夏季休闲裤男薄款大码长裤宽松直筒男裤冰丝超薄西裤男士裤子",
                // 顶层图片
                topImg: "img/6.jpg",
                // 商品图片
                imgs: [
                    "img/1.jpg",
                    "img/2.jpg",
                    "img/3.jpg",
                    "img/4.jpg",
                ],
                // 是否参加电竞节
                isActivity: false,
                // 是否支持信用卡
                isCard: true,
                // 是否支持七天退货
                isSeven: true,
                // 是否如实描述
                isRealDesc: true,
                isChecked:false,
                // 规格
                spec: "<p>颜色:宝蓝色【5023款】+宝蓝色【5023】</p><p>尺码:28[腰围2尺10]</p>",
                marketPrice: 200,
                // 单价
                price: 168.00,
                // 购买的数量
                count: 0,
                // 金额
                amount: 336.00
            }
        ]
    },
    {
        // 购物车编号
        cartId: 3,
        // 店铺编号 
        shopId: 2003,
        // 店铺名称
        isChecked:false,
        shopName: "雅鹿提趣专卖店",
        products: [
            {
                // 商品编号
                productId: 1004,
                // 商品名称
                productName: "雅鹿天丝休闲裤男士夏季薄款商务修身长裤子直筒西裤夏天冰丝男裤",
                // 顶层图片
                topImg: "img/7.jpg",
                // 商品图片
                imgs: [
                    "img/1.jpg",
                    "img/2.jpg",
                    "img/3.jpg",
                    "img/4.jpg",
                ],
                // 是否参加电竞节
                isActivity: false,
                // 是否支持信用卡
                isCard: true,
                // 是否支持七天退货
                isSeven: true,
                // 是否如实描述
                isRealDesc: true,
                isChecked:false,
                // 规格
                spec: "<p>颜色:660卡其(单件)</p><p>尺码:29</p>",
                marketPrice: 200,
                // 单价
                price: 118.00,
                // 购买的数量
                count: 0,
                // 金额
                amount: 118.00
            }
        ]
    }
]

4.img文件夹中,自己选择图片即可

 5.index.html中内容如下

<!DOCTYPE html>
<html lang="zh-cn">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>购物车</title>
		<link rel="stylesheet" href="css/style.css">
		<script src="./js/data.js"></script>
		<script src="https://unpkg.com/vue@3"></script>
	</head>
	<body>
	
	<div id="app"></div>
	<template id="root">

		<div class="shop-cart">
			<div class="tabs">
				<div class="border" >
					
					<div :class="t.mclass" data-index="index" v-for="(t,index) in tabbars" :key="index" @mouseenter="active(t,index,tabbars)">
						{{t.text}}
						<span class="count">{{t.count}}</span>
					</div>
					<div class="line" :style="{left:offsetWidth}"></div>
				</div>
			</div>

			<div class="lists">

				<div class="header">
					<ul class="clearfix">
						<li>
							<!-- <input type="checkbox" class="select-all" v-model="allCheck" @change="checkAll"> -->
							<span @click="checkAll()" :class="allCheck?['ckb_s']:['ckb']"></span>
							<label >全选</label>
						</li>
						<li class="product-info">商品信息</li>
						<li>单价</li>
						<li>数量</li>
						<li>金额</li>
						<li>操作</li>
					</ul>
				</div>

				<!-- 实验需要操作的节点 -->
				<div id="shoplist" class="shoplist">
					<!-- 店铺内容及样式参考 -->
					
					<div class="shop" v-for="(item,index) in shopcarts" :key="item.shopId" >
						<div class="shop-info" >
													<!-- 二级方法要传值 ,v-model不能与@点击事件方法名一样-->
							<!-- <input type="checkbox"  @change="selectShopItems(item)" v-model="item.isChecked"> -->
							<div  @click="selectShopItems(item)" :class="item.isChecked?['ckb_s']:['ckb']"></div>
							<span class="shop-tip">店铺:</span>
							<a class="shop-name" href="#">{{item.shopName}}</a>
							<a href="#" class="wangwang">旺旺</a>
						</div>

						<div class="products" >
							<div class="item" v-for="(p,index) in item.products" :class="(index+1)%2==0?['even']:['even1']">

								<div class="select-logo">
													<!-- 三级方法要传值 ,v-model绑定事件-->
									<!-- <input type="text"  @change="selectProductItem(item,p)"  v-model="p.isChecked" @click="changes()" > -->
									<div type="text"  @click="selectProductItem(item,p)"   :class="p.isChecked?['ckb_s']:['ckb']"></div>
									<img :src="p.topImg" alt="产品logo">
								</div>

								<div class="product-detail">
									<div class="left">
										<a href="#" class="product-name">
											{{p.productName}}
										</a>
										<div class="logos">
											<a href="#" class="card"  >信用卡</a>
											<a href="#" class="service" >保障服务</a>
											<a href="#" class="order" >订单险</a>
											<a href="#" class="seven" >7天无理由</a>
										</div>
									</div>

									<div class="right">
										<!-- 解析掉标签 -->
										<p v-html="p.spec"></p>
									</div>

								</div>

								<div class="price">
									<p class="market-price">¥{{p.marketPrice}}</p>
									<p class="real-price">¥{{p.price}}</p>
								</div>

								<div class="count">
									<span class="sub" @click="changeProductCount(p,'sub')" ><span :class="p.count==0?['bb']:['cc']">-</span></span>
									<span class="input"><input type="text" v-model="p.count"></span>
									<span class="add" @click="changeProductCount(p,'add')">+</span>
								</div>

								<div class="amount">¥{{p.price*p.count}}</div>
								<div class="delete" >
									<a href="#" @click="handRemove(item,p)">删除</a>
								</div>
							</div>
						</div>

					</div>
					
				</div>
			</div>

			<div class="operate">
				<div class="left">
					<input type="checkbox" class="select-all-footer">
					<a href="javascript:void(0);" @click="removeAll">删除</a>
				</div>

				<div class="right">
					<div>已选择商品<span class="selected-count">{{number}}</span>件</div>
					<div class="amount">合计(不含运费): <span class="sum">¥{{sumPrice}}</span></div>
					<a href="javascript:void(0);" class="settle">结算</a>
				</div>
			</div>
		</div>
	</template>
		
		<script>
			
     Vue.createApp({
        template: '#root',
			data() {
				return {
					shopcarts,
					sumPrice:0,
					number:0,
					//v-model的绑定对象
					allCheck:false,
					tabbars:[{text:'全部商品',count:3,mclass:'title  active'},{text:'降价商品',count:0,mclass:'title'},{text:'库存紧张',count:0,mclass:'title  last'}],
					offsetWidth:0,
				}
			},	
			watch:{
				shopcarts:{
					handler(nvalue,ovalue){
						this.sumPrice=0
						this.number=0
						nvalue.forEach(item => {
						item.products.forEach((p)=>{
							if(p.isChecked){
								this.sumPrice +=(p.price*p.count)
								this.number +=p.count
							}
						})
					 })
					},	
					deep:true,
					immediate:true
				}
			},
			methods: {
				
				//选择框
				active(t,index,tabbars){
					tabbars.forEach((item)=>{
						item.mclass="title"
					})
					t.mclass="title active"
					this.offsetWidth=(index*123)+"px"
				},

				//反选
				selectProductItem(item,p) {
					p.isChecked=!p.isChecked
					let num = item.products.filter((p)=>{return p.isChecked}).length
					if(num == item.products.length){
						item.isChecked=true
					}else{
						item.isChecked=false
					}
				},
				//店铺全选
				selectShopItems(item) {
					item.isChecked=!item.isChecked

					item.products.forEach((p)=>{
							p.isChecked=item.isChecked
						})
				},
				//数量改变
				changeProductCount(p, type) {
					if(type === "add"){
						 p.count++ ;
					}
					if(type === "sub"&& p.count>=1){
						p.count--;
					}
				},
				//删除
				handRemove(item,p){
					item.products.splice(item.products.indexOf(p),1)
					if(item.products.length<=0){
						this.shopcarts.splice(this.shopcarts.indexOf(item),1)
					}
				},
				//删除全部
				removeAll(item){
					this.shopcarts.splice(0,this.shopcarts.length)
				},

				//所有全选
				checkAll(){
					this.allCheck=!this.allCheck

					if(this.allCheck){
						console.log(this.allCheck);
						this.shopcarts.forEach((item)=>{
							item.isChecked=true
							item.products.forEach((p)=>{
								p.isChecked=true
							})
						})
					}
					else{
						console.log(this.allCheck);
						this.shopcarts.forEach((item)=>{
							item.isChecked=false
							item.products.forEach((p)=>{
								p.isChecked=false
							})
						})
					}
					
				}
			}
      }).mount('#app')
		</script>
	</body>
</html>

6.效果图展示

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐