uniapp + Vue3 购物车页面实现遇到非常有意思的 update:num 值更新双向绑定

uniapp + Vue3 购物车页面实现遇到非常有意思的 update:num 值更新双向绑定

1、效果展示

在这里插入图片描述

2、子组件


这里我发现问题,如果不传入商品的 id ,那么我们应该怎样判断我们修改的是那个商品的数量,从而计算总价?

我突然发现向父组件传值有个这个东西
const emit = defineEmits([‘update:num’])
那么 update:num 是什么东西,我是第一次见。
原来这个是实现子父组件双向绑定值,那么我父组件直接利用
v-model:num=‘item.number’
后发现当数量发生变化时,总价也同步计算了。真的神奇。

值得注意:一定要在 num 前加 update 才有效果。

<template>
	<view style="width: 240rpx;">
		<view class="flex flex-aic xlb_input_number_box b_2 bgc_f8f8f8">
			<view class="xlb_input_number_btn tac b_r_2" :class="numberVal <= 1 ? 'color_999' : 'color_333'" @tap="updateNum(true)">-</view>
			<input @blur="inputNum" type="number" v-model="numberVal" class="xlb_input_number_ipt flex-fitem tac font_28" />
			<view class="xlb_input_number_btn tac b_l_2" :class="numberVal >= max ? 'color_999' : 'color_333'"  @tap="updateNum(false)">+</view>
		</view>
	</view>
</template>

<script setup>
	import {
		ref,
		watchEffect
	} from 'vue'
	import lyzDebounce from "@/js_sdk/lyz-debounce/lyz-debounce.js"
	let numberVal = ref(1)
	let props = defineProps({
		num: {
			type: Number,
			default: 1
		},
		max: {
			type: Number,
			default: 99999
		}
	});
	watchEffect(() => {
		numberVal.value = props.num
	})
	const inputNum = (e) => {
		if(isNaN(e.detail.value)) {
			numberVal.value = 1
			emitFun(numberVal.value)
		}else if (Number(e.detail.value) <= 0 || e.detail.value == 'e') {
			numberVal.value = 1
			emitFun(numberVal.value)
		} else if (Number(e.detail.value) > props.max) {
			numberVal.value = props.max
			emitFun(numberVal.value)
		} else {
			emitFun(Number(e.detail.value))
		}
	}
	const emitFun = lyzDebounce.debounce((val) => {
		emit('update:num', val)
	}, 200, false)
	const emit = defineEmits(['update:num'])
	const updateNum = (flg) => {
		if (flg) {
			if (numberVal.value - 1 <= 0) return
			emitFun(numberVal.value -= 1)
		} else {
			if (props.max !== 0 && props.max < numberVal.value + 1) return
			emitFun(numberVal.value += 1)
		}
	}
</script>

<style lang='scss' scoped>
	.xlb_input_number_box {
		height: 64rpx;
	}

	.xlb_input_number_ipt {
		margin: 0 10rpx;
		border: none;
	}

	.xlb_input_number_btn {
		width: 64rpx;
		height: 64rpx;
		line-height: 64rpx;
	}
</style>

3、父页面

<template>
	<view class="shop_tool_view">
		<view class="shop_tool_box flex-aic flexr-jfe boxs_bb pos_f bgc_fff">
			<text>完成</text>
		</view>
	</view>
	<view class="shop_list_view">
		<view class="bgc_fff shop_list_box">
			<template v-for="(item,index) in shopData" :key="index">
				<view class="flex flex-aic p_t_24">
					<radio style="transform:scale(0.6)" :checked="item.isChoose"
						@tap="item.isChoose=!item.isChoose;choose();" color="#fe5572" />
					<image class="shop_item_img m_r_16" :src="item.image" mode="aspectFill"></image>
					<view class="flex-fitem">
						<view class="color_333 font_26 m_b_8">{{item.title}}</view>
						<view class="flex flex-aic m_b_4">
							<view class="color_999 font_24 m_r_24">{{item.type}}</view>
							<uni-icons type="bottom" size="14" color="#999999"></uni-icons>
						</view>
						<view class="flex-aic flexr-jsb">
							<view class="color_ff0003">
								<text class="font_28">¥</text>
								<text class="font_40">{{item.price}}</text>
							</view>
							<lyz-input-num v-model:num='item.number'></lyz-input-num>
						</view>
					</view>
				</view>
			</template>
		</view>
	</view>
	<view class="shop_nav_box pos_f bgc_fff flex-aic flexr-jsb boxs_bb">
		<label class="flex flex-aic color_999 font_24">
			<radio style="transform:scale(0.7)" color="#fe5572" @tap="allChoose" :checked="isAllChoose" />全选
		</label>
		<view class="flex-fitem flex-aic flexr-jfe m_r_16">
			<text class="font_28 color_333">合计:</text>
			<view class="color_ff7000">
				<text class="font_28">¥</text>
				<text class="font_40">{{allPrice}}</text>
			</view>
		</view>
		<lyz-button borderColor="#fe5572" backgroundColor="#fe5572">
			<template #title>
				<view class="pos_r flex flex-aic flex-fitem" style="height: 100%;">
					<text>结算</text>
					<text class="pos_a btn_shop_a bgc_fff color_ff7000 font_16">{{ allNumber}}</text>
				</view>
			</template>
		</lyz-button>
	</view>
</template>

<script setup>
	import {
		computed,
		reactive,
		ref
	} from 'vue';
	
	// 全选
	const choose = () => {
		shopData.forEach(x => {
			if (x.isChoose == false) {
				isAllChoose.value = false;
			}
		})
	}
	const isAllChoose = ref(false);
	const allChoose = () => {
		if (!isAllChoose.value) {
			shopData.forEach(x => x.isChoose = true)
			isAllChoose.value = true;
		} else {
			shopData.forEach(x => x.isChoose = false)
			isAllChoose.value = false;
		}
	}
	// 计算价格
	const allPrice = computed(() => {
		let count = 0;
		shopData.filter(x => x.isChoose).forEach(x => {
			count += (x.price) * x.number;
		})
		return count.toFixed(2);
	})
	// 计算总数
	const allNumber = computed(() => {
		let count = 0;
		shopData.filter(x => x.isChoose).forEach(x => {
			count += x.number;
		})
		return count;
	})
	const shopData = reactive([{
			id: 1,
			image: '',
			title: '鱼腥草折耳根嫩叶子侧耳根猪鼻孔凉拌菜农家自种新鲜',
			price: 9.90,
			number: 2,
			type: "新鲜折耳根;1kg",
			isChoose: false
		},
		{
			id: 2,
			image: '',
			title: '四川豌豆尖新鲜蔬菜现摘现发豌豆苗碗豆菜火锅菜露天龙须菜5斤',
			price: 19.90,
			number: 1,
			type: "新鲜豌豆尖;1kg",
			isChoose: false
		},
		{
			id: 3,
			image: '',
			title: '遵义会议水杯纪念品礼物红军长征茶杯礼品工艺收藏品摆设摆件杯子',
			price: 25.00,
			number: 1,
			type: "红色水杯;1个",
			isChoose: false
		},
		{
			id: 4,
			image: '',
			title: '复古纯手工编织红军草鞋男女士麻鞋舞台表演道具夏季系带全麻凉鞋',
			price: 28.00,
			number: 1,
			type: "手工凉鞋;1双;42.5码",
			isChoose: false
		}
	])
</script>

<style lang="scss" scoped>
	.shop_list_view {
		padding: 24rpx 32rpx;
	}

	.shop_list_box {
		padding: 0 20rpx 20rpx 0;
		border-radius: 12rpx;
	}

	.shop_item_img {
		width: 152rpx;
		height: 152rpx;
		border-radius: 6rpx;
	}

	.shop_tool_view {
		width: 100%;
		height: 88rpx;
	}

	.shop_tool_box {
		height: 88rpx;
		left: 0;
		right: 0;
		z-index: 1;
		padding-right: 32rpx;
	}

	.shop_nav_box {
		width: 100%;
		height: 100rpx;
		box-shadow: 0rpx -2rpx 6rpx 0rpx rgba(215, 215, 215, 0.5);
		bottom: calc(100rpx);
		bottom: calc(constant(safe-area-inset-bottom) + 100rpx);
		bottom: calc(env(safe-area-inset-bottom) + 100rpx);
		left: 0;
		right: 0;
		z-index: 1;
		padding: 0 32rpx 0 16rpx;
	}

	.btn_shop_a {
		padding: 0 8rpx;
		height: 24rpx;
		top: 10rpx;
		right: -16rpx;
		line-height: 26rpx;
		border-radius: 24rpx;
	}
</style>
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
uniapp是一个基于Vue.js的跨平台开发框架,而Vue3是Vue.js的最新版本。它们的结合可以带来更好的开发体验和性能优化。uniapp提供了导航栏双页切换的功能,而Vue3的Pinia框架则提供了参数输出和方法调用的功能,还支持模块化和持久化存储。如果您有关于uniappVue3的使用问题,您可以查看uniapp官网获取更详细的信息和示例代码。uniapp在早期版本中开始支持Vue3的使用,并且从HBuilderX 3.2版本开始支持创建基于Vue3的uniapp项目。使用uniappVue3开发项目的流程与常规的Vue3开发类似。您可以按照官方提供的升级指南和使用文档来进行开发。希望以上信息对您有所帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [uniapp+vue3+pinia框架(模块化+持久化存储)](https://download.csdn.net/download/qq_35079107/87910679)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [uniapp + vue3微信小程序开发(1)框架搭建](https://blog.csdn.net/qq_39404437/article/details/124345386)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [uniapp开发:uniapp之切换vue3,一直使用一直爽](https://blog.csdn.net/qq_42961150/article/details/121375073)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

她似晚风般温柔789

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值