UNIAPP优购商城购物车功能

目录

一、购物车页面

(1)、qxc-address(收货地址)

2、qxc-goods(购物车显示商品信息)

3、qxc-settle(购物车结算页面)

4、购物车页面


前言:由于uniapp拥有高效开发,性能优秀,功能扩展灵活等优点,吸引了无数电商企业使用uniapp一次开发多个平台应用和部署,而今天要讲的,就是多渠道经营的卖家要开发商城中不可或缺的功能:购物车

那么首先,我们需要写出地址框,购物车标题,购物车统计,以及购物车为空时的页面

一、购物车页面

<template>
	<view v-if="cart.length!==0">
		<!-- 地址框 -->
		<qxc-address :address="address"></qxc-address>
		<!-- 购物车标题 -->
		<view class="cart-title">
			<text class="iconfont icon-tuya_huabanfuben">购物车</text>
			<uni-icons class="item-img" type="cart"></uni-icons>
		</view>
		<!-- 购物车列表 -->
		<view>
			<qxc-goods v-for="(item,index) in cart" :key="index" :goods='item' :showCheck='true' :showNum="true"
				:allowLongTap="true" @changeNum='changeNum' @changChacked="changChacked">
			</qxc-goods>
		</view>
		<!-- 购物车统计 -->
		<qxc-settle :buttonText="'结算'" :showAllCheck="true" :cartData='cart' @changAllCheck='changAllCheck'>
		</qxc-settle>
		</view>
		<!-- 购物车为空时 -->
		<view class="cart-default" v-else>
			<view class="default-image">
				<image class="cart-image" src="../../static/cart_empty.png" mode="widthFix"></image>
			</view>
			<view class="default-text">
				购物车空空如也
			</view>
		</view>


</template>

以上代码是一个 UniApp 页面的模板代码,使用了条件渲染来展示购物车的内容。根据 `cart` 数组的长度,当购物车不为空时,会渲染购物车的地址框、标题、列表和统计部分;当购物车为空时,会显示一个空购物车的提示信息。

具体来看:

<view v-if="cart.length!==0">`:根据 `cart` 数组的长度判断购物车是否为空,如果不为空,则渲染下面的内容。
<qxc-address :address="address"></qxc-address>`:展示购物车的地址框,通过 address="address"` 将 `address` 对象传递给 `qxc-address` 组件。
<view class="cart-title">`:购物车的标题部分,包括一个文字标题和一个购物车图标。
<view>:购物车的列表部分,使用 `v-for` 循环遍历 `cart` 数组中的每个商品,将商品数据传递给 `qxc-goods` 组件进行渲染。
 `<qxc-settle>`:购物车的结算部分,展示结算按钮和全选功能,通过 `:buttonText`、`showAllCheck` 和 `cartData` 属性将相应的数据传递给 `qxc-settle` 组件。
 `<view class="cart-default" v-else>`:当购物车为空时,显示购物车为空的提示信息。
`<image class="cart-image" src="../../static/cart_empty.png" mode="widthFix"></image>`:显示一个空购物车的图片。
 `<view class="default-text">购物车空空如也</view>`:显示一个提示文本,表示购物车为空。

这段代码使用了多个自定义组件(例如 `qxc-address`、`qxc-goods` 和 `qxc-settle`),

(1)、qxc-address(收货地址)

<template>
	<view class="address">

		<view class="address-button" v-if="!address.userName">
			<button type="primary" size="mini" @click="getAddress" open-type="openSetting">+添加收货地址</button>
		</view>

		<view class="address-info" v-else @tap="getAddress">
			<view class="name-phone">
				<view class="username">
					收货人:{{address.userName}}
				</view>
				<view class="phone">
					电话:{{address.telNumber}}
					<uni-icons type="arrowright" size="16"></uni-icons>
				</view>
			</view>
			<view class="address">
				收货地址:{{allAddress}}
			</view>
		</view>
		
	</view>
</template>

<script>
	export default {
		name: "qxc-address",
		data() {
			return {

			}
		},
		
		
			props: ['address'],
			methods: {
				async getAddress() {
					//1.获取收获地址
					const res = await uni.chooseAddress();
					console.log(res)
					//2.用户成功的选择了收货地址
					if (res.errMsg == 'chooseAddress:ok') {
						uni.setStorageSync('address',res)
					}
				}

			},
			computed: {
				allAddress() {
						let str=this.address.provinceName+this.address.countyName + this.address.cityName + this.address.detailInfo
						return str
					}
				},
		}
</script>

1.在<template>标签内,首先定义了一个名为address的<view>元素,用于包裹整个收货地址的展示区域。
2. 在<view>元素内,使用了条件渲染(v-if)和点击事件(@click),根据address.userName是否存在来判断是否显示"添加收货地址"按钮。
3. 如果address.userName不存在,则显示一个<view>元素,内部包含一个<button>元素,点击按钮会触发getAddress方法。
4. 如果address.userName存在,则显示一个<view>元素,内部包含两个<view>元素,分别用于显示收货人姓名和电话号码,并且还使用了一个<uni-icons>组件来显示一个箭头图标。
5. 最后,还有一个<view>元素,用于显示完整的收货地址信息,该信息由计算属性allAddress生成。

在<script>标签内,首先使用export default导出了一个对象,该对象包含了组件的名称、data、props、methods和computed等属性。

1. data()方法返回一个空对象。
2. props属性用于接收组件外部传入的数据,这里接收了一个名为address的属性。
3. getAddress()方法是一个异步方法,用于获取用户的收货地址。它使用了uni.chooseAddress()方法来弹出微信小程序的收货地址选择界面,并将选择结果保存在res变量中。
4. 如果用户成功选择了收货地址,则会在控制台打印出选择结果,并将结果存储在uni.setStorageSync()中。
5. computed计算属性allAddress用于拼接收货地址的各个部分,生成完整的收货地址字符串。

该组件的功能是在页面上显示收货地址信息,并提供添加收货地址的功能。当用户点击添加收货地址按钮时,会弹出微信小程序的收货地址选择界面,用户选择成功后,选择结果会保存在本地存储中,并显示在页面上。

2、qxc-goods(购物车显示商品信息)

<template>
	<view class="goods" @click="getclick" @longtap="deleteGoods">
		<view class="image-box" @click.stop>
			<checkbox v-if='showCheck' :checked="goods.checked" @click.stop="changChacked"/>
			<image :src="goods.goods_big_logo ||defaultImg" mode="widthFix"></image>
		</view>
		<view class="goods-info">
			<!-- 商品名称 -->
			<view class="goods-name">
				{{goods.goods_name}}
			</view>
			<view class="goods-price-box">
				<!-- 商品价格 -->
				<view class="goods-price">
					¥{{goods.goods_price}}
				</view>
				<!-- 购物车中商品数量编辑框 -->
				<view class="good-num" v-if="vshowNum">
					<view class="num-edit" @tap.stop='numSub' :class="goods.cartNum===1?'one':''">-</view>
					<view class="num">{{goods.cartNum}}</view>
					<view class="num-edit" @tap.stop="numAdd">+</view>
				</view>
				<!-- 支付页用的 -->
				<view class="only" v-if="vshowNumOnly" @tap.stop="showNumEdit">
					x{{goods.cartNum}}
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		name:"qxc-goods",
		data() {
			return {
				defaultImg:'../../static/logo.png',//商品默认图片
				//用于数量编辑框与x数量框的切换
				vshowNum:this.showNum,
				vshowNumOnly:this.showNumOnly
			};
		},
		// props:['goods'],
		props:{
			goods:{
				type:Object,
				default:null
			},
			//是否显示复选框
			showCheck:{
				type:Boolean,
				default:false
			},
			//是否显示数量编辑器
			showNum:{
				type:Boolean,
				default:false
			},
			//是否允许长按进行删除
			allowLongTap:{
				type:Boolean,
				default:false
			},
			//是否显示 X数量
			showNumOnly:{
				type:Boolean,
				default:false
			},
		},
			methods:{
				showNumEdit(){
					this.vshowNumOnly=false;
					this.vshowNum=true;
				},
				changChacked(){
					
					this.$emit("changChacked",{
						goods_id: this.goods.goods_id,
						checked: !this.goods.checked
					})
				},
				//长按 删除
				deleteGoods(){
					if(this.allowLongTap){
						uni.showModal({
							title:'删除',
							content:'确定删除吗?',
							success: (res) =>{
								console.log(res);
								if (res.confirm){
									this.$emit('changeNum',{
										goods_id:this.goods.goods_id,
										cartNum:0,
									})
								}
							}
						})
					}
				},
				//单击 +
				numAdd(){
					this.$emit('changeNum',{
						goods_id: this.goods.goods_id,
						cartNum: this.goods.cartNum + 1,
					})
				},
				//单机 -
				numSub(){
					if (this.goods.cartNum > 1){
					this.$emit('changeNum',{
						goods_id: this.goods.goods_id,
						cartNum: this.goods.cartNum - 1,
					})
				}
				},
				
				getclick(){
					uni.navigateTo({
						url:'../../subpkg1/goods-detail/goods-detail?goods_id='+this.goods.goods_id
					})
				}
			}
	}

这段代码用于显示商品信息

1. `<template>` 标签中定义了组件的模板结构,包括商品的图片、名称、价格等信息,以及一些交互操作。

2. `<script>` 标签中定义了组件的逻辑部分,包括组件的名称、数据、属性和方法。

3. 在 `data` 中定义了一个默认的商品图片路径 `defaultImg`,这个路径指向了一个静态资源 `logo.png`。

4. `props` 中定义了组件的属性,包括 `goods`(商品信息对象)、`showCheck`(是否显示复选框)、`showNum`(是否显示数量编辑器)、`allowLongTap`(是否允许长按删除)、`showNumOnly`(是否显示 X 数量)等。

5. `methods` 中定义了组件的方法,包括 `showNumEdit`(切换数量编辑框和 X 数量显示框)、`changChacked`(切换商品的选中状态)、`deleteGoods`(长按删除商品)、`numAdd`(增加商品数量)、`numSub`(减少商品数量)以及 `getclick`(点击跳转到商品详情页)等。

总体来说,这个组件可以根据传入的商品信息来显示商品的图片、名称、价格等信息,并且提供了一些交互操作,如选择复选框、编辑数量、长按删除等。同时,还可以通过点击商品跳转到商品详情页。

3、qxc-settle(购物车结算页面)

<template>
	<view class="cart-tool">
		<view class="tool-selectAll" v-if='showAllCheck'>
			<checkbox-group @change="changAllCheck">
				<label>
					<checkbox color="var(--themeColor)" :checked="allChecked" />
					<text>全选</text>
				</label>
			</checkbox-group>
		</view>
		<view class="total-price-box">
			<view class="total-price">合计:<text class="price-text">¥{{totalPrice}}</text></view>
			<view class="runway-text">包含运费</view>
		</view>
		<view class="settle" @tap="gotopay">{{buttonText}}({{totalSum}})</view>

	</view>
</template>

<script>
	export default {
		name: "qxc-settle",
		data() {
			return {

			};
		},
		props: {
			cartData: {
				type: Array,
				default: []
			},
			// 是否显示复选框
			buttonText: {
				type: String,
				default: '结算'
			},
			// 是否显示

			showAllCheck: {
				type: Boolean,
				default: false
			},
		},
		methods: {

			async gotopay() {
				// uni.navigateTo({
				// 	url:'../../subpkg2/goods-pay/goods-pay'
				// })
				if (this.buttonText == '结算') {
					const address = uni.getStorageSync('address');
					//判断是否存在收货地址
					if (!address.userName) {
						uni.showToast({
							title: "还没有选择收货地址",
							icon: 'none'
						});
						return;
					}
					//判断是否选择商品

					if (this.totalSum === 0) {
						uni.showToast({
							title: "还没有选择商品",
							icon: 'none'
						});
						return;
					}
					//3.跳转到支付页面
					uni.navigateTo({
						url: '../../subpkg2/pay/pay'
					});

				} else if (this.buttonText == '支付') {
					try {
						//1.判断是否存在token地址
						const token = uni.getStorageSync('token');
						//2.没有跳转到登录页面
						if (!token) {
							uni.setStorageSync('page', 'pay');
							uni.navigateTo({
								url: '../../subpkg2/login/login'
							})
							return;
							}
					//跳转到订单页面
								uni.reLaunch({
									url:'../../subpkg2/order/order'
								})
							} catch (e) {
								uni.showToast({
									title: '支付失败',
									icon: 'none'
								});
							}
						}
					},

			changAllCheck() {
				this.$emit('changAllCheck', !this.allChecked)
			}
		},
		computed: {
			allChecked() {
				return this.cartData.every(v => v.checked)
			},
			totalPrice() {
				let sum = 0;
				this.cartData.forEach(v => {
					if (v.checked) {
						sum += v.cartNum * v.goods_price
					}
				})
				return sum;
			},
			totalSum() {
				let num = 0;
				this.cartData.forEach(v => {
					if (v.checked) {
						num += v.cartNum
					}
				})
				return num;
			}

		},
	}
</script>

用于购物车结算页面的展示和操作:

在template部分,首先是一个view标签,class为"cart-tool",用于包裹以下的结算工具栏内容。其中,view标签下有三个子view标签,分别是:
1. class为"tool-selectAll"的view标签,用于显示全选的复选框。该复选框使用了checkbox组件,并通过checkbox-group实现了全选功能。
2. class为"total-price-box"的view标签,用于显示合计价格。其中,class为"total-price"的view标签用于显示合计文案,class为"price-text"的text标签用于显示具体的价格。另外,还有一个class为"runway-text"的view标签用于显示包含运费的文案。
3. class为"settle"的view标签,用于显示结算按钮。按钮的文案通过props传入,显示的内容为"结算"或"支付",同时显示购物车中选中的商品数量。

在script部分,export default导出了一个对象,其中包含了组件的相关配置和逻辑:
1. name属性为"qxc-settle",用于组件的命名。
2. data方法返回一个空对象,用于存放组件的数据。
3. props属性定义了组件的props,包括cartData、buttonText和showAllCheck。其中,cartData为购物车的数据,buttonText为结算按钮的文案,showAllCheck表示是否显示全选的复选框。
4. methods属性定义了组件的方法。其中,gotopay方法用于处理点击结算按钮的逻辑。在gotopay方法中,首先判断按钮文案,如果为"结算",则会判断是否选择了收货地址和商品;如果为"支付",则会判断是否存在token。根据判断结果进行相应的跳转操作。
5. changAllCheck方法用于处理全选复选框的变化事件,通过$emit方法将变化的值传递给父组件。
6. computed属性定义了组件的计算属性。其中,allChecked计算属性用于判断是否全选,通过检查cartData中的每个元素的checked属性来判断;totalPrice计算属性用于计算选中商品的合计价格;totalSum计算属性用于计算选中商品的数量。

总结:这是一个UniApp的购物车结算组件,包含了全选、合计价格和结算按钮的展示和操作。通过props传入购物车数据和按钮文案,通过方法和计算属性处理按钮点击和数据的变动。

4、购物车页面

回到购物车页面中,我们还有剩余的script代码未完成

<script>
	export default {
		data() {
			return {
				cart: [],
				address:{},
			}
		},
		//不能使用onload,否则从商品详情页加入购物车,再点击'购物车'后,购物车没有及时更新数据
		onShow() {
			//从缓存获取购物车数据
			this.cart = uni.getStorageSync('cart') || [];
			//从缓存获取地址数据
			this.address = uni.getStorageSync('address') || {};
			
		},

		methods: {
			changAllCheck(e) {
				this.cart.forEach(v => v.checked = e);
			},

			//修改购物车相应产品的选中状态
			changChacked(e) {
				let index = this.cart.findIndex(v => v.goods_id == e.goods_id);
				this.cart[index].checked = e.checked;
				//更改缓存中的购物车
				uni.setStorageSync('cart', this.cart);
			},

			//修改购物车相应产品的数量
			//5.31做了更改加了if 移了let index和最后储存的变量放入else
			changeNum(e) {
				let index = this.cart.findIndex(v => v.goods_id == e.goods_id);
				if (e.cartNum == 0) {
					this.cart.splice(index, 1)
				} else {
					this.cart[index].cartNum = e.cartNum;
				}
				// this.cart[index].cartNum = e.cartNum;	
				//更改缓存中的购物车
				uni.setStorageSync('cart', this.cart);
			},
		},
	}

</script>

这段代码是一个UniApp的页面组件,用于展示购物车的功能。以下是代码的功能说明:

1. data中定义了两个数据属性:cart用于存储购物车商品列表,address用于存储收货地址信息。
2. onShow函数在页面展示时被调用,用于从缓存中获取购物车和地址数据。
3. methods中定义了几个方法:
   - changAllCheck方法用于全选或取消全选购物车商品。
   - changChacked方法用于修改购物车中某个商品的选中状态。
   - changeNum方法用于修改购物车中某个商品的数量,如果数量为0则从购物车中移除该商品。

最后,使用export default将组件导出,以供其他页面使用。

这样,我们的购物车页面代码就完成了。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值