注意的是;要为接口返回值指定类型 ,以及定义接口数据类型
index.ets
import { http } from '@kit.NetworkKit';interface createAtType {date: number,}interface dataListType {createAt: createAtType;imgUrl: ''
}@Component
export default struct TabBar {@State dataList: dataListType[] = []aboutToAppear() {console.log(`我是组件钩子函数:aboutToAppear`)let http1 = http.createHttp();let responseResult = http1.request('https://www.grosup.com/banner/getall/0', {method: http.RequestMethod.GET,header: {'Content-Type': 'application/json'},readTimeout: 20000,connectTimeout: 10000});let serverData: ResponseResult = new ResponseResult();responseResult.then((value: http.HttpResponse) => {let res = JSON.stringify(value)let result = `${value.result}`;let resCode = `${value.code}`console.log('result1', result)let resultObj: object = JSON.parse(result) //一定要指定类型,不然无法获取属性console.log('result2', JSON.stringify(resultObj['data']['list'])) //this.dataList = resultObj['data']['list']}).catch(() => {})}build {Column() {Text('测试网络')// Text(JSON.stringify(this.dataList))ForEach(this.dataList, (item: dataListType) => {GridItem() {Column() {Image(item.imgUrl).objectFit(ImageFit.Cover).width('100%').height('200')// Text(item.createAt?.date)Text(item.imgUrl)}}.onClick(() => {})}, (item: dataListType, index: number) => `${item}_${index}`)}}}
定义接口类型使用interface和class的区别
建议使用class接收接口数据,因为interface不能逻辑复用与封装,直接使用又容易出现类型安全问题而导致APP闪退
很多人讲,请求接口数据要为每个接口特地写一个类很麻烦,这里用一个示例聊聊不使用类与使用类的区别。
import { plainToClass } from 'class-transformer'class Ohter {dateofBirth: string = ""
}class User {name: string = ""ohter?: OhtergetAge() {if(!this.ohter){return '数据异常'}const today = new Date();const birthDate = new Date(this.ohter.dateofBirth);let age = today.getFullYear() - birthDate.getFullYear();return age;}
}@Entry
@Component
struct Page043 {userJson: string = `{ "name":"张三","ohter":{"dateofBirth":"2000-01-01"}}`userJson_2: string = `{ "name":"李四" }`build() {Column() {Button('测试').onClick(() => {//方案一:直接使用JSON.parse+[] ,服务端数据正常时const today = new Date();const birthDate = new Date(JSON.parse(this.userJson)['ohter']['dateofBirth']);let age = today.getFullYear() - birthDate.getFullYear();console.info(`姓名:${JSON.parse(this.userJson)['name']}`)console.info(`年龄:${age}`)})Button('测试2').onClick(() => {//方案二:将数据处理封装到class内let users: User = plainToClass(User, JSON.parse(this.userJson))console.info(`姓名:${users.name}`)console.info(`年龄:${users.getAge()}`)})Button('测试3').onClick(() => {//方案三:直接使用JSON.parse+[] ,服务端数据异常时,闪退const today = new Date();const birthDate = new Date(JSON.parse(this.userJson_2)['ohter']['dateofBirth']);let age = today.getFullYear() - birthDate.getFullYear();console.info(`姓名:${JSON.parse(this.userJson)['name']}`)console.info(`年龄:${age}`)})Button('测试4').onClick(() => {//方案四:将数据处理封装到class内 ,服务端数据异常时let users: User = plainToClass(User, JSON.parse(this.userJson_2))console.info(`姓名:${users.name}`)console.info(`年龄:${users.getAge()}`)})}.width('100%').height('100%')}
}
总结:
方案一没使用任何框架,也不需要为接口写类, [] 就能拿到数据,拿到后,需要自己获取一下年,做减法,才能知道这个人的真实年龄。这是最正常的写法。
方案二相比方案一,体验了封装class的好处,可以把复杂的逻辑封装到class内,而不必把一堆逻辑代码暴露在page内。
方案三体现了方案一的缺点,万一接口数据给的不正常,方案一这种很容易拿不到数据,导致app崩溃
方案四体现了class的另一个好处,就是可以在内部事先加判断,避免接口数据不正确而导致app崩溃
【总结】使用class的好处是
1、代码可读性和维护性提升:可以对属性添加注释、使得开发者能够更容易理解数据的组成和用途,这对于团队协作和长期维护是非常有利的。
2、类型安全:通过类的定义提前预防这类错误,而不是在运行时遭遇异常或“闪退”。
3、逻辑复用与封装:数据处理逻辑被集中在一处,便于修改和复用。
4、易于扩展和继承:类支持继承,允许你基于现有类创建更具体的子类,轻松添加或覆盖功能。这为软件的未来扩展提供了便利。
5、错误处理更加优雅:提高了应用的健壮性。