问题:
简单的业务我们通过Index来删除,但是复杂的业务用index来删除就会出现错误,比如说购物车列表我删除数据,如果用index来删除就会出现删了第一个之后,后面的数据index都是一样的。
import { CartGood, goodList } from '../data/GoodData'
import { promptAction } from '@kit.ArkUI'
import { it } from '@ohos/hypium'
const MAIN_RED: string = '#f4304b'
const LIGHT_GRAY: string = '#f5f5f5'
const DEEP_GRAY: string = '#bebebe'
@Entry
@Component
struct Main {
@State
list: CartGood[] = goodList
@Provide totalPrice:number=0
@Provide totalCount:number=0
@State
@Watch('eventChange')
eventArray:string[] =[]
eventChange(){
this.totalPrice = this.list.filter((item:CartGood)=>{
return this.eventArray.includes(item.id)
}).reduce((total:number,item:CartGood)=>{
return total + item.count * item.good.jdPrice
},0)
this.totalCount = this.list.filter((item:CartGood)=>{
return this.eventArray.includes(item.id)
}).reduce((total:number,item:CartGood)=>{
return total + item.count
},0)
}
build() {
Column() {
// 标题
TitleCom({count:this.list.length})
// 内容
ContentCom({list:this.list})
// 支付
PayCom({eventArray:this.eventArray})
}
.height('100%')
.backgroundColor(LIGHT_GRAY)
}
}
// 内容区域
@Component
struct ContentCom {
@Link list:CartGood[]
build() {
Scroll() {
Column() {
// 支付
FreightCom()
.margin(10)
// 商品列表
Column({ space: 10 }) {
ListTitleCom()
// 自营区域
List() {
ForEach(this.list, (item: CartGood, index: number) => {
ListItem() {
GoodsListItem({
good:item
})
}
.swipeAction({end:this.delBuilder(item.id)})
// .swipeAction({end:this.delBuilder(index)})
})
}
.divider({ strokeWidth: .5, startMargin: 10, endMargin: 10, color: DEEP_GRAY })
}
.backgroundColor(Color.White)
.margin({ left: 10, right: 10 })
// 空车 商品为空时显示
if (this.list.length === 0){
EmptyCom()
}
}
}
.align(Alignment.Top)
.padding({ bottom: 10 })
.edgeEffect(EdgeEffect.Spring)
.layoutWeight(1)
}
@Builder
delBuilder(id:string){
// delBuilder(index:number){
Column(){
Text('删除')
.fontSize(20)
.fontColor(Color.White)
.onClick(()=>{
this.list = this.list.filter(item => item.id !== id)
promptAction.openToast({
message: '删除成功',
})
// this.list.splice(index,1)
})
}
.justifyContent(FlexAlign.Center)
.width('20%')
.height('100%')
.backgroundColor(Color.Red)
}
}
// 标题(显示商品种类)
@Component
struct TitleCom {
@Prop count:number = 0
build() {
Row() {
// 文字
Stack({ alignContent: Alignment.Bottom }) {
Text(`购物车(${this.count} )`)
.height('100%')
Text('')
.width(25)
.height(2)
.linearGradient({ angle: 90, colors: [[MAIN_RED, 0], [Color.White, 1]] })
}
.height('100%')
// 地址
Row() {
Image($r('app.media.ic_yhd_location'))
.width(15)
.fillColor(DEEP_GRAY)
Text('北京市海淀区')
.fontSize(12)
.fontColor(DEEP_GRAY)
}
.height(20)
.padding({ left: 5, right: 5 })
.borderRadius(10)
.backgroundColor(LIGHT_GRAY)
// 编辑
Text('编辑')
}
.padding({ left: 20, right: 20 })
.width('100%')
.height(40)
.justifyContent(FlexAlign.SpaceBetween)
.backgroundColor(Color.White)
}
}
// 运费(地址下方)
@Component
struct FreightCom {
// 默认 69 可以由外部传入
minPrice: number = 69.00
// totalPrice: number = 0
@Consume ('totalPrice')totalPrice:number
build() {
Column() {
if (this.totalPrice > this.minPrice){
// 运费足够 提示
Row({ space: 5 }) {
Text('运费')
.backgroundColor(MAIN_RED)
.fontSize(12)
.fontColor(Color.White)
.padding(2)
.borderRadius(3)
Divider()
.vertical(true)
.height(12)
.strokeWidth(2)
Text('已免运费')
.fontSize(12)
.fontColor(Color.Gray)
Image('/common/day08-10/yhd/ic_yhd_order_info.png')
.width(15)
}
}else {
// 运费不够 提示
Row() {
Row({ space: 5 }) {
// 凑单免运费
Text() {
Span('凑单')
Span('免运费')
.fontColor(MAIN_RED)
}
.fontSize(13)
.fontFamily('medium')
// 分割线
Divider()
.vertical(true)
.height(8)
.color(DEEP_GRAY)
.strokeWidth(1)
// 运费信息
Row() {
Text() {
Span('还需凑钱 ')
Span(`¥${(this.minPrice - this.totalPrice).toFixed(2)}`)
.fontColor(MAIN_RED)
Span('可免运费')
}
.fontSize(13)
Image($r('app.media.ic_yhd_order_info'))
.width(15)
}
}
// 按钮
Button() {
Row() {
Text('去凑单')
.fontColor(Color.White)
.fontSize(12)
Image($r('app.media.ic_public_arrow_right'))
.height(14)
.width(10)
.fillColor(Color.White)
}
.backgroundColor(MAIN_RED)
.borderRadius(20)
.padding({ left: 10, top: 3, bottom: 3, right: 2 })
}
}
.width('100%')
}
}
.borderRadius(5)
.height(30)
.padding({ left: 8, right: 8 })
.linearGradient({ colors: [['#ffe8ea', 0], [Color.White, 1]] })
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
// 支付(最下方组件)
@Component
struct PayCom {
@Link eventArray:string[]
@Consume ('totalPrice')totalPrice:number
@Consume ('totalCount')totalCount:number
build() {
Row() {
Row() {
CheckboxGroup({
group: 'cart'
})
.selectedColor(MAIN_RED)
.onChange((event)=>{
this.eventArray = event.name
})
Text('全选')
.fontSize(12)
}
Row() {
Text('合计:')
.fontSize(14)
PriceCom({
fontColor: Color.Black,
price: this.totalPrice
})
Button(`入会结算(${this.totalCount})`)
.fontColor('#ffe3cc')
.backgroundColor(Color.Black)
.fontSize(14)
.margin({ left: 5 })
}
}
.justifyContent(FlexAlign.SpaceBetween)
.padding({ left: 10, right: 10 })
.height(48)
.width('100%')
.backgroundColor(Color.White)
}
}
// 价格(根据传入的价格渲染数字)
@Component
struct PriceCom {
@Prop price: number = 0
fontColor: ResourceColor = MAIN_RED
discard: boolean = false
getSplicePrice() {
return this.price.toFixed(2)
.split('.')
}
build() {
Text() {
Span('¥')
.fontSize(12)
Span(this.getSplicePrice()[0]
.toString())
.fontSize(this.discard ? 12 : 16)
.fontWeight(600)
Span('.')
Span(this.getSplicePrice()[1] == undefined ? '00' : this.getSplicePrice()[1])
.fontSize(12)
}
.fontColor(this.fontColor)
.decoration({ type: this.discard ? TextDecorationType.LineThrough : TextDecorationType.None })
}
}
// 空车:购物车为空显示
@Component
struct EmptyCom {
build() {
Column({ space: 20 }) {
Image($r('app.media.ic_yhd_cart_empty'))
.width(90)
Text('购物车竟然是空的~')
.fontSize(14)
.fontColor(Color.Gray)
}
.width('100%')
.backgroundColor(Color.White)
.padding(50)
}
}
// 列表区域标题:装饰用
@Component
struct ListTitleCom {
build() {
Row({ space: 5 }) {
Image($r('app.media.ic_yhd_logo'))
.width(12)
Text('自营')
.fontWeight(600)
.fontSize(15)
Divider()
.vertical(true)
.height(10)
.strokeWidth(2)
Text('1号会员店提供服务')
.fontColor(DEEP_GRAY)
.fontSize(12)
}
.alignSelf(ItemAlign.Start)
.padding({ left: 15, top: 10 })
}
}
// 列表项:
@Component
struct GoodsListItem {
@ObjectLink good:CartGood
build() {
Row({ space: 10 }) {
// 左
Checkbox({
group: 'cart',
name:this.good.id
})
.shape(CheckBoxShape.CIRCLE)
.selectedColor(MAIN_RED)
// 右
Row({ space: 8 }) {
// 商品图片
Image(this.good.good.imageurl)
.width(90)
.padding(5)
.border({ width: .5, color: DEEP_GRAY })
.borderRadius(10)
// 信息
Column() {
// 标题
Text(this.good.good.wname)
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize(14)
.fontWeight(400)
.width('100%')
// 价格 + 数量
Row() {
Column() {
// 左
Row() {
Image($r('app.media.ic_yhd_hyj'))
.width(35)
PriceCom({ price: this.good.good.jdPrice })
}
PriceCom({ discard: true, fontColor: DEEP_GRAY, price: this.good.good.jdMainPrice })
}
.alignItems(HorizontalAlign.Start)
Blank()
// 个数 Counter 内置组件
Counter() {
Text( this.good.count.toString())
}
.enableInc(true)
.enableDec(this.good.count > 1)
.onInc(() => {
this.good.count += 1
})
.onDec(() => {
this.good.count -= 1
})
.scale({ x: .8, y: .8 })
}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
}
.height(90)
.justifyContent(FlexAlign.SpaceBetween)
.layoutWeight(1)
}
.layoutWeight(1)
}
.padding({ left: 10, top: 10, bottom: 10 })
}
}
解决方案:
因为id是唯一的,我们通过传递id来进行删除,我们首先在builder构建函数中接收id值,把需要删除的数据删除,需要留下来的数据做一个重新渲染,用到数组的filter方法,让item.id不等于id,因为如果相等的话我们就相当于把这个id保留下来了,此时其他数据全部被删除,只有点击删除的这个数据没有被删除,所以不能等于这个id(filter筛选的条件为true的时候数据就会保留下来,那么我想删除这个数据,只需要让item的id和id不相等,此时为true数据才会保留下来),并且我们还需要给forEach设定第三个参数,如果没有第三个参数默认用索引来进行渲染。具体操作如下: