父子组件之间的双向绑定,妙用v-model

本文作者分享了如何通过Vue框架和HBuilderX工具优化ERP项目的采购模块,利用v-model双向绑定减少了代码量,实现实时商品预估价格计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1:因为此前erp项目中的采购模块添加商品,实时计算单个商品预估价格及全部商品总额折磨了我很久,所以今天闲来无事优化一下,使用另一种思维来做一个类似demo,作为此前总结反思

2:原来项目模块是这样的

3:demo案列如下

父组件app.vue

<script setup>
import { ref,computed } from 'vue'
import goods from './goods.vue'
let goodsList=ref([])
let goodsName=['苹','果','香','焦','桃','子','西','瓜','黄','冬']
const addGoods=()=>{
  goodsList.value.push({id:Math.random(),name:goodsName[Math.floor(Math.random()*10)],inputPrice:'',computedPrice:'',qty:'1',})
}
let total=computed(()=>{
  return goodsList.value.reduce((total,item)=>total+item.computedPrice,0)
})
</script>

<template>
  <div>
    <div v-for="(item,index) in goodsList" :key="item.id">
      <goods v-model:goodsList="goodsList" v-model:goodsItem="goodsList[index]" />
    </div>
    <div>商品总价:{{ total }}</div>
  </div>


  <div style="text-align: center;width: 300px;">
    <span @click="addGoods">添加商品+</span>
  </div>
</template>

子组件goods.vue

<script setup>
import {computed} from 'vue'
const goodsList = defineModel('goodsList')
const goodsItem = defineModel('goodsItem')
goodsItem.value.computedPrice=computed(()=>goodsItem.value.inputPrice*goodsItem.value.qty)
const deleteGoods=()=>{
  let index=goodsList.value.findIndex((item)=>item.id==goodsItem.value.id)
  goodsList.value.splice(index,1)
}
</script>

<template>
  <div class="goods">
    <div class="deleteGoods" @click="deleteGoods">-</div>
    <div class="head">
      <div class="title">商品名:{{ goodsItem.name }}</div>
      <div class="number">
        <div class="jian" @click="goodsItem.qty>1&&goodsItem.qty--">-</div>
        <input v-model="goodsItem.qty"/>
        <div class="jia" @click="goodsItem.qty++">+</div>
      </div>
    </div>
    <div class="main">
      <input placeholder="请输入价格" v-model="goodsItem.inputPrice"/>
    </div>
    <div class="footer">
      <div v-if="goodsItem.computedPrice">
        <span>商品价格:</span>
        <span>{{ goodsItem.computedPrice }}</span>
      </div>
    </div>
  </div>
</template>
<style>
.goods{
  width: 300px;
  border: 1px solid red;
  padding: 10px;
  margin-top: 20px;
  position: relative;
  .deleteGoods{
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background-color: #ccc;
    text-align: center;
    position: absolute;
    top: -15px;
    right: -15px;
  }
  .head{
    display: flex;
    justify-content: space-between;
    margin-bottom: 20px;
    .number{
      display: flex;
      .jian,.jia{
        width: 30px;
        text-align: center;
        font-weight: 700;
        border: 1px solid #ccc;
      }
      input{
        width: 50px;
      }
    }
  }
  .main{
    width: 290px;
    margin-bottom: 10px;
    input{
      width: 100%;
    }
  }
  .footer{

  }
}
</style>

页面效果如下

如有任何疑问,欢迎在评论区提出,谢谢阅读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值