OpenHarmony应用开发-构建完整实例

素年锦时静待君丶
发布于 2023-4-12 17:55
浏览
0收藏

版本:v3.2 Beta5

构建食物数据模型

在创建视图中,我们逐一去表述食物的各个信息,如食物名称、卡路里、蛋白质、脂肪、碳水和维生素C。这样的编码形式在实际的开发中肯定是不切实际的,所以要创建食物数据模型来统一存储和管理数据。

OpenHarmony应用开发-构建完整实例-鸿蒙开发者社区

  1. 新建model文件夹,在model目录下创建FoodData.ets。

OpenHarmony应用开发-构建完整实例-鸿蒙开发者社区

  1. 定义食物数据的存储模型FoodData和枚举变量Category,FoodData类包含食物id、名称(name)、分类(category)、图片(image)、热量(calories)、蛋白质(protein)、脂肪(fat)、碳水(carbohydrates)和维生素C(vitaminC)属性。 ArkTS语言是在ts语言的基础上的扩展,同样支持ts语法。

enum Category  {
  Fruit,
  Vegetable,
  Nut,
  Seafood,
  Dessert
}

let NextId = 0;
class FoodData {
  id: string;
  name: string;
  image: Resource;
  category: Category;
  calories: number;
  protein: number;
  fat: number;
  carbohydrates: number;
  vitaminC: number;

  constructor(name: string, image: Resource, category: Category, calories: number, protein: number, fat: number, carbohydrates: number, vitaminC: number) {
    this.id = `${ NextId++ }`;
    this.name = name;
    this.image = image;
    this.category = category;
    this.calories = calories;
    this.protein = protein;
    this.fat = fat;
    this.carbohydrates = carbohydrates;
    this.vitaminC = vitaminC;
  }
}
  1. 存入食物图片资源。在resources >base> media目录下存入食物图片资源,图片名称为食物名称。
  2. 创建食物资源数据。在model文件夹下创建FoodDataModels.ets,在该页面中声明食物成分数组FoodComposition。以下示例创建了两个食物数据。

const FoodComposition: any[] = [
  { 'name': 'Tomato', 'image': $r('app.media.Tomato'), 'category': Category.Vegetable, 'calories': 17, 'protein': 0.9, 'fat': 0.2, 'carbohydrates': 3.9, 'vitaminC': 17.8 },
  { 'name': 'Walnut', 'image': $r('app.media.Walnut'), 'category': Category.Nut, 'calories': 654 , 'protein': 15, 'fat': 65, 'carbohydrates': 14, 'vitaminC': 1.3 }
  ]

实际开发中,开发者可以自定义更多的数据资源,当食物资源很多时,建议使用​​数据懒加载LazyForEach​​。

  1. 创建initializeOnStartUp方法来初始化FoodData的数组。在FoodDataModels.ets中使用了定义在FoodData.ets的FoodData和Category,所以要将FoodData.ets的FoodData类export,在FoodDataModels.ets内import FoodData和Category。

// FoodData.ets
export enum Category {
 ......
}
export class FoodData {
  ......
}
// FoodDataModels.ets
import { Category, FoodData } from './FoodData'

export function initializeOnStartup(): Array<FoodData> {
  let FoodDataArray: Array<FoodData> = []
  FoodComposition.forEach(item => {
    FoodDataArray.push(new FoodData(item.name, item.image, item.category, item.calories, item.protein, item.fat, item.carbohydrates, item.vitaminC ));
  })
  return FoodDataArray;
}

已完成好健康饮食应用的数据资源准备,接下来将通过加载这些数据来创建食物列表页面。

相关实例

针对构建食物分类列表页面和食物详情页,有以下相关实例可供参考:

构建食物列表List布局

使用List组件和ForEach循环渲染,构建食物列表布局。

  1. 在pages目录新建页面FoodCategoryList.ets,将index.ets改名为FoodDetail.ets。
  2. 新建FoodList组件作为页面入口组件,FoodListItem为其子组件。List组件是列表组件,适用于重复同类数据的展示,其子组件为ListItem,适用于展示列表中的单元。

@Component
struct FoodListItem {
  build() {}
}

@Entry
@Component
struct FoodList {
  build() {
    List() {
      ListItem() {
        FoodListItem()
      }
    }
  }
}
  1. 引入FoodData类和initializeOnStartup方法。

应用代码中文件访问方法主要有下面两种:

  • 相对路径:使用相对路径引用代码文件,以"…/“访问上一级目录,以”./"访问当前目录,也可以省略不写。
  • 绝对路径:使用当前模块根路径引用代码文件,比如:common/utils/utils。 这里使用相对路径访问:

import { FoodData } from '../model/FoodData'
import { initializeOnStartup } from '../model/FoodDataModels'
  1. FoodList和FoodListItem组件数值传递。在FoodList组件内创建类型为FoodData[]成员变量foodItems,调用initializeOnStartup方法为其赋值。在FoodListItem组件内创建类型为FoodData的成员变量foodItem。将父组件foodItems数组的第一个元素的foodItems[0]作为参数传递给FoodListItem。

import { FoodData } from '../model/FoodData'
import { initializeOnStartup } from '../model/FoodDataModels'

@Component
struct FoodListItem {
  private foodItem: FoodData
  build() {}
}

@Entry
@Component
struct FoodList {
  private foodItems: FoodData[] = initializeOnStartup()
  build() {
    List() {
      ListItem() {
        FoodListItem({ foodItem: this.foodItems[0] })
      }
    }
  }
}
  1. 声明子组件FoodListItem 的UI布局。创建Flex组件,包含食物图片缩略图,食物名称,和食物对应的卡路里。

import { FoodData } from '../model/FoodData'
import { initializeOnStartup } from '../model/FoodDataModels'

   @Component
   struct FoodListItem {
     private foodItem: FoodData
     build() {
       Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
         Image(this.foodItem.image)
           .objectFit(ImageFit.Contain)
           .height(40)
           .width(40)
           .margin({ right: 16 })
         Text(this.foodItem.name)
           .fontSize(14)
           .flexGrow(1)
         Text(this.foodItem.calories + ' kcal')
           .fontSize(14)
       }
       .height(64)
       .margin({ right: 24, left:32 })
     }
   }

@Entry
   @Component
   struct FoodList {
     private foodItems: FoodData[] = initializeOnStartup()
     build() {
       List() {
         ListItem() {
           FoodListItem({ foodItem: this.foodItems[0] })
         }
       }
     }
   }

OpenHarmony应用开发-构建完整实例-鸿蒙开发者社区

  1. 创建两个FoodListItem。在List组件创建两个FoodListItem,分别给FoodListItem传递foodItems数组的第一个元素this.foodItems[0]和第二个元素foodItem: this.foodItems[1]。

import { FoodData } from '../model/FoodData'
import { initializeOnStartup } from '../model/FoodDataModels'

@Component
struct FoodListItem {
  private foodItem: FoodData

  build() {
    Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
      Image(this.foodItem.image)
        .objectFit(ImageFit.Contain)
        .height(40)
        .width(40)
        .margin({ right: 16 })
      Text(this.foodItem.name)
        .fontSize(14)
        .flexGrow(1)
      Text(this.foodItem.calories + ' kcal')
        .fontSize(14)
    }
    .height(64)
    .margin({ right: 24, left: 32 })
  }
}

@Entry
@Component
struct FoodList {
  private foodItems: FoodData[] = initializeOnStartup()

  build() {
    List() {
      ListItem() {
        FoodListItem({ foodItem: this.foodItems[0] })
      }

      ListItem() {
        FoodListItem({ foodItem: this.foodItems[1] })
      }
    }
  }
}

OpenHarmony应用开发-构建完整实例-鸿蒙开发者社区

  1. 单独创建每一个FoodListItem肯定是不合理的,这就需要引入​​ForEach循环渲染​​。

import { FoodData } from '../model/FoodData'
import { initializeOnStartup } from '../model/FoodDataModels'

@Component
struct FoodListItem {
  private foodItem: FoodData
  build() {
    Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
      Image(this.foodItem.image)
        .objectFit(ImageFit.Contain)
        .height(40)
        .width(40)     
        .margin({ right: 16 })
      Text(this.foodItem.name)
        .fontSize(14)
        .flexGrow(1)
      Text(this.foodItem.calories + ' kcal')
        .fontSize(14)
    }
    .height(64)
    .margin({ right: 24, left:32 })
  }
}

@Entry
@Component
struct FoodList {
  private foodItems: FoodData[] = initializeOnStartup()
  build() {
    List() {
      ForEach(this.foodItems, item => {
        ListItem() {
          FoodListItem({ foodItem: item })
        }
      }, item => item.id.toString())
    }
  }
}
  1. 添加FoodList标题。

@Entry
@Component
struct FoodList {
  private foodItems: FoodData[] = initializeOnStartup()

  build() {
    Column() {
      Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
        Text('Food List')
          .fontSize(20)
          .margin({ left: 20 })
      }
      .height('7%')
      .backgroundColor('#FFf1f3f5')

      List() {
        ForEach(this.foodItems, item => {
          ListItem() {
            FoodListItem({ foodItem: item })
          }
        }, item => item.id.toString())
      }
      .height('93%')
    }
  }
}

OpenHarmony应用开发-构建完整实例-鸿蒙开发者社区



文章转载自:​​https://docs.openharmony.cn/pages/v3.2Beta/zh-cn/application-dev/ui/ui-ts-building-category-list-layout.md/​

已于2023-4-12 17:55:47修改
收藏
回复
举报
回复
    相关推荐