今日学习复盘:HarmonyOS 数据结构与歌单界面实战

1. 核心理论:数组与对象的深度理解

今日重点攻克了 ArkTS 中两种最基础也最重要的数据结构,它们是构建复杂应用界面的基石。

📦 数组 (Array):同类数据的集合

  • 定义:用于存储类型相同的一组数据。
  • 语法let 数组名: 类型[] = [数据1, 数据2, ...]
  • 应用场景:歌单列表、商品列表、消息流等需要批量渲染的场景。
  • 关键点:在 ArkTS 中,强类型约束要求数组内的元素必须严格符合声明的类型,这有助于在编译期发现错误。

    💡 示例let scores: number[] = [90, 85, 92];

🗂️ 对象 (Object):异构数据的模型

  • 定义:用于描述一个实体,通过键值对 (Key-Value) 存储不同类型的属性。
  • 语法
    let entity: EntityType = {
      key1: value1, // 属性名: 属性值
      key2: value2
    };
    
  • 访问方式:使用点符号 对象名.属性名 获取具体值。
    • ⚠️ 注意:直接打印对象(如 console.log(obj))在某些环境下可能只显示 [object Object],无法直观看到内部数据。调试时建议打印具体属性或使用 JSON.stringify()
  • 应用场景:定义用户信息、歌曲详情、商品属性等具有多个维度的数据模型。

2. 实战任务:静态歌单数据 Mock 与界面展示

✅ 任务目标:定义 SongItem 核心数据结构,完成静态数据 Mock,并渲染出美观的歌单列表。

📂 项目结构规划

为了保持代码的清晰与可维护性,采用了标准的分层目录结构:

entry-src-main-ets/
├── data/                # 存放模拟数据 (Mock Data)
│   └── Mockdata.ets
├── model/               # 存放数据模型接口 (Interfaces)
│   └── SongItem.ets
└── pages/               # 存放页面逻辑
    └── Index.ets

💻 核心代码实现详解

① 数据模型定义 (model/SongItem.ets)

不仅定义了数据接口,还封装了通用的工具函数,体现了高内聚的设计思想。

// 定义歌曲数据接口,确保数据类型安全
export interface SongItem {
  id: number;          // 唯一标识
  title: string;       // 歌名
  artist: string;      // 歌手
  album: string;       // 专辑
  duration: number;    // 时长 (秒)
  coverUrl: string;    // 封面链接
  audioUrl: string;    // 音频链接
  isLiked: boolean;    // 是否收藏
}

/**
 * 工具函数:将秒数格式化为 "分:秒" (例如 269 -> "4:29")
 * 逻辑:Math.floor 取整分钟,% 运算取余秒,padStart 补零
 */
export function formatDuration(seconds: number): string {
  const minutes = Math.floor(seconds / 60);
  const remainingSeconds = seconds % 60;
  // 确保秒数始终为两位数,如 5 -> "05"
  return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
}
② 模拟数据构造 (data/Mockdata.ets)

构建了包含 5 首歌曲的测试数据集,涵盖了中英文歌曲及不同的收藏状态,用于验证列表渲染的多样性。

import type { SongItem } from '../model/SongItem';

export const MOCK_SONG_LIST: SongItem[] = [
  {
    id: 1,
    title: "晴天",
    artist: "周杰伦",
    album: "叶惠美",
    duration: 269,
    coverUrl: "https://picsum.photos/200/200?random=1", // 随机占位图
    audioUrl: "", 
    isLiked: true
  },
  {
    id: 2,
    title: "起风了",
    artist: "买辣椒也用券",
    album: "起风了",
    duration: 325,
    coverUrl: "https://picsum.photos/200/200?random=2",
    audioUrl: "",
    isLiked: false
  },
  // ... (其他歌曲数据略,保持结构一致)
];
③ 界面渲染逻辑 (pages/Index.ets)

利用 ArkUI 的声明式语法,结合 ListForEach 实现高效列表渲染。

✨ 亮点优化:

  1. 状态管理:使用 @State 装饰 songList,确保数据变化时视图自动刷新。
  2. 唯一 KeyForEach 的第三个参数 (item) => item.id.toString() 至关重要,它帮助框架识别列表项的唯一性,提升渲染性能。
  3. 布局细节
    • 使用 layoutWeight(1) 让歌曲信息列自动占据剩余空间,防止时长文本换行。
    • 添加 borderRadiusbackgroundColor 提升卡片质感。
    • 使用 ImageFit.Cover 确保封面图片不变形填充。
@Entry
@Component
struct Index {
  // 绑定状态数据,初始值为 Mock 数据
  @State songList: SongItem[] = MOCK_SONG_LIST;

  build() {
    Column() {
      Text('我的歌单')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20, bottom: 10 })

      List({ space: 10 }) {
        ForEach(this.songList, (item: SongItem) => {
          ListItem() {
            Row() {
              // 1. 封面图片
              Image(item.coverUrl)
                .width(60)
                .height(60)
                .borderRadius(8)
                .objectFit(ImageFit.Cover)

              // 2. 歌曲文本信息
              Column({ space: 5 }) {
                Text(item.title)
                  .fontSize(16)
                  .fontWeight(FontWeight.Medium)
                Text(`${item.artist} - ${item.album}`)
                  .fontSize(12)
                  .fontColor('#666666')
              }
              .layoutWeight(1) // 关键:自适应宽度
              .margin({ left: 10 })

              // 3. 格式化后的时长
              Text(formatDuration(item.duration))
                .fontSize(12)
                .fontColor('#999999')
            }
            .padding(10)
            .backgroundColor('#FFFFFF')
            .borderRadius(10)
          }
        }, (item: SongItem) => item.id.toString()) // 必须提供唯一 Key
      }
      .padding(10)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F1F3F5') // 整体背景色
  }
}

3. 运行效果与反思

🖼️ 最终展示

成功在虚拟机中渲染出歌单界面,列表项整齐排列,图片加载正常,时长格式正确(如 4:29),UI 风格简洁现代。
在这里插入图片描述

💡 学习心得与注意事项

  1. 类型安全的重要性:通过 interface 定义数据模型,使得在编写 UI 代码时能获得完整的智能提示,减少了拼写错误。
  2. 时间格式化逻辑padStart(2, '0') 是一个非常实用的字符串方法,在处理时间、日期格式化时经常用到。
  3. 列表性能:在 ForEach 中生成唯一的 key 是避免列表渲染错乱或性能低下的关键,切忌使用数组索引 index 作为 key(如果列表会发生增删操作)。
  4. 资源加载:目前使用的是网络随机图 (picsum.photos),实际开发中应替换为本地资源 $r('app.media.xxx') 或真实的 CDN 链接,并注意处理图片加载失败的情况。
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐