【HarmonyOS实战】 数据模型设计:StationData接口与静态数据怎么组织? 文章目录前言一、StationData 文件全貌二、interface 还是 class2.1 interface 的特点2.2 class 的特点2.3 选 interface 的理由三、ResourceStr 是什么类型四、静态数据的组织方式五、数据在组件中如何使用5.1 声明列表状态5.2 遍历列表渲染 UI5.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.idid;this.namename;}getFullInfo():string{return${this.name};}}// 必须用 new 创建letstationnewStationData(1,中国石化AA站);class有完整的面向对象能力但在只需要存储数据时class是多余的。2.3 选 interface 的理由维度interfaceclass运行时开销无有原型链、构造器创建方式字面量对象直接满足必须new有无方法不能定义实现可以定义方法适合场景纯数据传输对象DTO有行为的领域对象加油站数据只是数据容器没有行为所以interface更合适、更轻量。三、ResourceStr 是什么类型exportinterfaceStationData{image:ResourceStr;// 注意这里不是 string而是 ResourceStr// ...}ResourceStr是 HarmonyOS ArkUI 框架提供的类型定义为typeResourceStrstring|Resource;它是一个联合类型可以是string普通字符串如网络图片 URLhttps://...Resource资源引用对象如$r(app.media.image1)在项目里图片用的是$r(app.media.image1)这种资源引用image:$r(app.media.image1),$r()返回的是Resource类型的对象包含资源 ID 等信息框架会自动解析成对应的图片。使用ResourceStr而不是string好处是可以同时支持网络图片string URL和本地资源Resource类型更精确编译器帮你检查四、静态数据的组织方式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.etsComponentstruct GasStationPage{StatestationInfoList:StationData[][];// 用 State 声明列表asyncinit():Promisevoid{// 从静态数据赋值实际项目这里通常是网络请求this.stationInfoListSTATION_LIST;}}5.2 遍历列表渲染 UIList(){ForEach(this.stationInfoList,(station:StationData){ListItem(){Row({space:Constants.SPACE_12}){this.stationInfoCard(station);// 把 StationData 传给卡片}};},(station:StationData){returnstation.idstation.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():Promisevoid{try{// 用 HTTP 请求获取数据letresponseawaithttp.request(https://api.example.com/stations);letdata:StationData[]JSON.parse(response.resultasstring);this.stationInfoListdata;}catch(err){Logger.error(获取加油站数据失败:${err.message});// 降级使用静态数据this.stationInfoListSTATION_LIST;}}StationData这个interface不需要改因为数据结构是一样的只是数据来源变了。这就是先定义好接口的好处——数据层和 UI 层解耦。总结数据模型设计的核心原则用 interface 而不是 class来定义纯数据结构轻量无额外开销用 ResourceStr替代 string支持资源引用和字符串双模式静态数据单独维护方便后续替换为网络请求用export导出接口和数据其他文件按需引入好的数据模型是项目可扩展性的基础定义清晰后面所有操作都会顺手很多。下一篇讲Logger 日志工具封装——为什么要自己封装一个 Logger而不是直接用console.log