☰
【HarmonyOS实战】 数据模型设计:StationData接口与静态数据怎么组织?
2026/10/6 7:13:02 网站建设 项目流程

文章目录

    • 前言
    • 一、StationData 文件全貌
    • 二、interface 还是 class?
      • 2.1 interface 的特点
      • 2.2 class 的特点
      • 2.3 选 interface 的理由
    • 三、ResourceStr 是什么类型?
    • 四、静态数据的组织方式
    • 五、数据在组件中如何使用
      • 5.1 声明列表状态
      • 5.2 遍历列表渲染 UI
      • 5.3 在卡片中使用数据
    • 六、坐标数据说明
    • 七、实际项目中如何扩展?
    • 总结

前言

每个应用都有数据。在"附近加油站"里,核心数据就是加油站列表——每个加油站有名字、地址、图片、经纬度。这些数据的结构定义在StationData.ets里。

这篇文章讲清楚:为什么用interface定义数据模型,ResourceStr是什么类型,静态数据怎么组织,以及这种设计在实际项目里的扩展思路。

项目预览

一、StationData 文件全貌

// entry/src/main/ets/model/StationData.ets// 定义加油站数据接口exportinterfaceStationData{image:ResourceStr;// 加油站图片(可以是字符串URL或资源引用)id:string;// 唯一标识符name:string;// 加油站名称addr:string;// 地址latitude:number;// 纬度longitude:number;// 经度}// 静态加油站数据列表exportconstSTATION_LIST:StationData[]=[{'image':$r('app.media.image1'),'id':'1','name':'中国石化加油站(AA站)','addr':'N市J区XX大街587号','latitude':31.937176963332842,'longitude':118.86018812656404,},{'image':$r('app.media.image2'),'id':'2','name':'中国石化加油站(BB站)','addr':'N市区软ZZ大道109号','latitude':31.925936403753692,'longitude':118.87239754199983,},{'image':$r('app.media.image3'),'id':'3','name':'中国石化加油站(CC站)','addr':'N市J区VV大街36号','latitude':31.930033972253533,'longitude':118.87715578079225,},{'image':$r('app.media.image1'),'id':'4','name':'中国石化加油站(DD站)','addr':'N市J区XX大街619号','latitude':31.929469429217495,'longitude':118.87800872325899,}];

二、interface 还是 class?

定义数据模型时,很多人习惯用class。但项目里用的是interface,为什么?

2.1 interface 的特点

// interface:纯粹的数据结构定义interfaceStationData{id:string;name:string;latitude:number;}// 创建对象(字面量方式)letstation:StationData={id:'1',name:'中国石化AA站',latitude:31.93,};

interface只是一个"形状描述",运行时没有对应的对象,零额外开销。

2.2 class 的特点

// class:有构造函数、方法、原型链classStationData{id:string;name:string;constructor(id:string,name:string){this.id=id;this.name=name;}getFullInfo():string{return`${this.name}`;}}// 必须用 new 创建letstation=newStationData('1','中国石化AA站');

class有完整的面向对象能力,但在只需要存储数据时,class是多余的。

2.3 选 interface 的理由

维度interfaceclass
运行时开销无有(原型链、构造器)
创建方式字面量对象直接满足必须new
有无方法不能定义实现可以定义方法
适合场景纯数据传输对象(DTO)有行为的领域对象

加油站数据只是"数据容器",没有行为,所以interface更合适、更轻量。

三、ResourceStr 是什么类型?

exportinterfaceStationData{image:ResourceStr;// 注意这里不是 string,而是 ResourceStr// ...}

ResourceStr是 HarmonyOS ArkUI 框架提供的类型,定义为:

typeResourceStr=string|Resource;

它是一个联合类型,可以是:

  • string:普通字符串(如网络图片 URL'https://...')
  • Resource:资源引用对象(如$r('app.media.image1'))

在项目里,图片用的是$r('app.media.image1')这种资源引用:

'image':$r('app.media.image1'),

$r()返回的是Resource类型的对象,包含资源 ID 等信息,框架会自动解析成对应的图片。

使用ResourceStr而不是string,好处是:

  1. 可以同时支持网络图片(string URL)和本地资源(Resource)
  2. 类型更精确,编译器帮你检查

四、静态数据的组织方式

exportconstSTATION_LIST:StationData[]=[{...},{...},{...},{...}];

const数组:STATION_LIST是常量,但数组本身的元素可以修改(const限制的是引用不变,不是内容不变)。

使用引号的 key:注意数组里的 key 用了引号('image'、'id'),这和不用引号(image、id)在 ArkTS 里效果一样,只是写法习惯不同。推荐不加引号(更简洁):

// 更简洁的写法(推荐){image:$r('app.media.image1'),id:'1',name:'中国石化加油站(AA站)',addr:'N市J区XX大街587号',latitude:31.937176963332842,longitude:118.86018812656404,}

五、数据在组件中如何使用

5.1 声明列表状态

// GasStationPage.ets@Componentstruct GasStationPage{@StatestationInfoList:StationData[]=[];// 用 @State 声明列表asyncinit():Promise<void>{// 从静态数据赋值(实际项目这里通常是网络请求)this.stationInfoList=STATION_LIST;}}

5.2 遍历列表渲染 UI

List(){ForEach(this.stationInfoList,(station:StationData)=>{ListItem(){Row({space:Constants.SPACE_12}){this.stationInfoCard(station);// 把 StationData 传给卡片}};},(station:StationData)=>{returnstation.id+station.name;// key 生成函数,用于高效更新});}

5.3 在卡片中使用数据

@BuilderstationInfoCard(gasStation:StationData):void{Column(){Image(gasStation.image)// 直接用 gasStation.imageText(gasStation.name)// 直接用 gasStation.nameText(gasStation.addr)// 直接用 gasStation.addr}}

六、坐标数据说明

'latitude':31.937176963332842,// 纬度'longitude':118.86018812656404,// 经度

注释里写了// Please configure it yourself,因为这是示例数据,这批坐标是位于某城市的真实坐标,你在使用时需要替换成你自己地区的加油站坐标。

纬度(latitude)和经度(longitude)的取值范围:

  • 纬度:-90(南极)到 +90(北极),中国约在 18°-53°
  • 经度:-180 到 +180,中国约在 73°-135°

这些坐标是WGS84 格式(GPS 原始坐标),在高德/腾讯地图上显示时需要转换为GCJ02 格式(中国地图坐标系),这个转换在后续的MapUtil里会详细讲。

七、实际项目中如何扩展?

项目现在用的是静态数据,真实应用通常从服务器拉数据。改造思路:

// 改造成从网络获取数据asyncinit():Promise<void>{try{// 用 HTTP 请求获取数据letresponse=awaithttp.request('https://api.example.com/stations');letdata:StationData[]=JSON.parse(response.resultasstring);this.stationInfoList=data;}catch(err){Logger.error(`获取加油站数据失败:${err.message}`);// 降级使用静态数据this.stationInfoList=STATION_LIST;}}

StationData这个interface不需要改,因为数据结构是一样的,只是数据来源变了。这就是先定义好接口的好处——数据层和 UI 层解耦。

总结

数据模型设计的核心原则:

  1. 用 interface 而不是 class来定义纯数据结构,轻量无额外开销
  2. 用 ResourceStr替代 string,支持资源引用和字符串双模式
  3. 静态数据单独维护,方便后续替换为网络请求
  4. 用export导出接口和数据,其他文件按需引入

好的数据模型是项目可扩展性的基础,定义清晰,后面所有操作都会顺手很多。

下一篇讲Logger 日志工具封装——为什么要自己封装一个 Logger,而不是直接用console.log?

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询