美团外卖-渲染商品菜单和列表

2024-02-06  本文已影响0人  家乡的蝈蝈

1.1、定义 model 数据模型

class FoodItem { //导出认为这个不存在, export表示这个类被别人引用
  id:number = 0
  name:string = ''
  like_rate_desc = ''
  month_saled:number = 0
  unit:string = ''
  food_tag_list:string[] = []
  price:number = 0
  picture:string = ''
  description:string = ''
  tag:string = ''
  count:number = 0
}

// 定义class类型
class Category {
  tag:string = ''
  name:string = ''
  foods:FoodItem[] = []
}

1.2、使用 http 发送请求,获取数据

import http from '@ohos.net.http'
@Entry
@Component
struct MeiTuan {
  @State list:Category[] = [] // 生命数据结构
  // 获取数据,将数据动态渲染
  aboutToAppear() { // 在组件初始化之后,在build之前去执行,只会执行一次
    // 获取美团餐饮数据
    this.getMTData()
  }
  async getMTData() {
    try {
      const req = http.createHttp()
      const res =await req.request("https://zhoushugang.gitee.io/fe2022/takeaway.json")
      this.list = JSON.parse(res.result as string) as Category[]
      // AlertDialog.show({message:this.list.length.toString()})
    } catch(e) {
    }
  }
  @State showCart:boolean = false
  build() {
    Stack({alignContent:Alignment.Bottom}) {
      // 主内容组件
      MTMain({list:$list})
      if (this.showCart) {
        // 购物车组件
        MTCart()
      }
      // 底部组件
      MTBottom({showCart:$showCart})
    }.height('100%')
  }
}

1.3、主体组件

// 主内容区组件
@Component
struct MTMain {
  @Link list:Category[]
  @State selectIndex:number = 0
  build() {
    Column() {
      MTNav()
      // 左侧是分类,右侧是菜品的结构
      Row() {
        // 左侧分类
        // 条件渲染不能用三元表达式-条件渲染:创建和销毁元素
        Column() {
          ForEach(this.list,(item:Category, index:number)=>{
            Text(item.name)
              .height(50)
              .width('100%')
              .fontSize(14)
              .textAlign(TextAlign.Center)
              .backgroundColor(this.selectIndex === index ? '#fff' : '#f5f5f5')
              .onClick(() => {
                this.selectIndex = index
              })
          })
        }.width(90)
        .height('100%')
        .backgroundColor('#f5f5f5')
        // 右侧内容
        // 放置若干个菜品数量
        List() {
          // ? || 为断路表达式 this.list[this.selectIndex] 有可能为undefind,?表示如果是undefined就不取foods,取[]
          ForEach(this.list[this.selectIndex]?.foods || [], (item:FoodItem) => {
            ListItem() {
              MTFoodItem({item:item})
            }
          })
        }
        .layoutWeight(1)
      }
      .width('100%')
      // .justifyContent(FlexAlign.Start)
      .alignItems(VerticalAlign.Top)
    }
    .height('100%')
    .width('100%')
  }
}

1.4、FoodItem组件使用属性接收数据并渲染

// 单品食物组件
@Component
struct MTFoodItem {
  item:Partial<FoodItem> = {}
  build() {
    Row() {
      Image(this.item.picture)
        .width(90)
        .aspectRatio(1)
      Column({ space: 5 }) {
        Text(this.item.name)
          .textOverflow({
            overflow: TextOverflow.Ellipsis,
          })
          .maxLines(2)
          .fontWeight(600)
        Text(this.item.description)
          .textOverflow({
            overflow: TextOverflow.Ellipsis,
          })
          .maxLines(1)
          .fontSize(12)
          .fontColor('#333')
        Text(this.item.unit)
          .fontSize(10)
          .backgroundColor('#fff5e2')
          .fontColor('#ff8000')
          .padding({ top: 2, bottom: 2, right: 5, left: 5 })
          .borderRadius(2)
        Text() {
          Span(`月销售40${this.item.month_saled}`)
          Span(' ')
          Span(this.item.like_rate_desc)
        }
        .fontSize(12)
        .fontColor('#999')

        Row() {
          Text() {
            Span('¥ ')
              .fontColor('#ff8000')
              .fontSize(10)
            Span(this.item.price.toFixed(2))
              .fontColor('#ff8000')
              .fontWeight(FontWeight.Bold)
          }
        }
        .justifyContent(FlexAlign.SpaceBetween)
        .width('100%')
      }
      .layoutWeight(1)
      .alignItems(HorizontalAlign.Start)
      .padding({ left: 10, right: 10 })
    }
    .padding(10)
    .alignItems(VerticalAlign.Top)
  }
}

1.5、底部组件使用Link控制购物车显示隐藏

// 底部组件
@Component
struct MTBottom {
  @Link showCart:boolean
  build() {
    Row() {
      .onClick(() => {
        this.showCart = !this.showCart
      })
    }
  }
}
上一篇 下一篇

猜你喜欢

热点阅读