当前位置:首页>鸿蒙APP>鸿蒙开发绕不开的四个核心问题,我整理了一份答案...

鸿蒙开发绕不开的四个核心问题,我整理了一份答案...

  • 2026-11-10 00:39:50
鸿蒙开发绕不开的四个核心问题,我整理了一份答案...
黄sir我做培训这些年,我发现学员问的问题,翻来覆去就那么几类。刚入门的时候问语法,学了一段时间问架构,真正做项目了问性能优化。今天把这四类高频问题系统梳理一遍,都是实战中踩出来的经验,没有废话。
问题一:状态管理到底怎么用才对
先说清楚原理:ArkUI的响应式系统,监听的是引用,不是属性。
// 错误,这样做,页面纹丝不动@State user: User = { name: '张三', age: 25 }this.user.name = '李四'// 正确,改了引用,UI才会刷新this.user = { ...this.user, name: '李四' }
搞清楚这个原理之后,@State、@Prop、@Link的区别就很好理解了:
@Entry@Componentstruct Parent {  @State parentCount: number = 0  @State userName: string = '学员'  build() {    Column() {      Text(`父组件: ${this.parentCount}`)      // @Prop:单向传值,子组件收到后是独立拷贝,改不了父组件      StatusDisplay({ label: '学习进度', value: this.userName })      // @Link:双向绑定,传的是引用,子组件改了父组件同步变      Counter({ count: $parentCount })    }  }}@Componentstruct Counter {  @Link count: number  // 双向绑定  build() {    Row() {      Button('计数-').onClick(() => this.count--)      Text(`${this.count}`).fontSize(24).fontWeight(FontWeight.Bold).margin({ left: 12, right: 12 })      Button('计数+').onClick(() => this.count++)    }  }}
记住一个原则:只读的数据用@Prop,需要双向联动的用@Link。
问题二:大列表卡顿怎么解决
列表卡顿这个问题,几乎每个项目组都会问到。很多人第一反应是手机性能不够?不是,是渲染方式有问题。
// 用ForEach渲染大数据量,必卡ForEach(this.products, (item: Product) => {  ListItem() { ProductCard({ product: item }) }}, (item: Product) => item.id)
ForEach一次性把所有数据都渲染出来,上千条的时候内存和渲染开销都会爆炸。换用LazyForEach,按需加载:
class ProductDataSource implements BasicDataSource {  private products: Product[] = []  totalCount(): number { return this.products.length }  getData(index: number): Product { return this.products[index] }  pushData(product: Product) {    this.products.push(product)    this.notifyDataAdd(this.products.length - 1)  }}List() {  LazyForEach(this.dataSource, (product: Product) => {    ListItem() {      Row() {        Text(product.name).fontSize(16)        Blank()        Text(`¥${product.price.toFixed(2)}`).fontColor('#FF6600')      }      .padding(16)    }  }, (product: Product) => product.id)}
打个比方:
ForEach:一次把所有商品都从仓库搬到货架上
LazyForEach:只搬货架能放下的那部分,看下一页再搬

问题三:如何设计一个合理的项目结构

项目大了必须分层。我推荐这个结构:

entry/src/main/ets/├── entryability/│   └── EntryAbility.ets          // 应用入口├── pages/│   └── Index.ets                // 首页├── view/│   ├── components/              // 可复用组件│   │   ├── HeaderBar.ets│   │   └── ProductCard.ets│   └── pages/                   // 页面组件│       ├── Detail.ets│       └── Settings.ets├── viewmodel/                   // 视图模型层│   ├── HomeViewModel.ets│   └── DetailViewModel.ets├── model/                       // 数据模型层│   ├── User.ets│   └── Product.ets├── service/                    // 服务层│   ├── HttpService.ets│   └── StorageService.ets└── utils/    ├── Logger.ets    └── Constants.ets
view层:只管UI渲染
viewmodel层:处理业务逻辑
model层:定义数据结构
service层:封装网络、数据库等能力
这样做的好处是什么?改东西的时候知道去哪找。页面换UI去view,逻辑要改去viewmodel,接口要换去service。

问题四:网络请求怎么封装才合理

直接用http模块裸写,每个接口都重复配置header、超时、错误处理,代码会变得又臭又长。

封装一层请求服务:

// http/HttpService.etsimport http from '@ohos.net.http';class HttpService {  private baseUrl: string = ''  private defaultHeaders: Record<string, string> = {    'Content-Type': 'application/json'  }  setToken(token: string) {    this.defaultHeaders['Authorization'] = `Bearer ${token}`  }  private async request<T>(url: string, method: http.RequestMethod, data?: object): Promise<T> {    const request = http.createHttp()    const fullUrl = this.baseUrl ? `${this.baseUrl}${url}` : url    const response = await request.request(fullUrl, {      method,      header: this.defaultHeaders,      extraData: data ? JSON.stringify(data) : undefined,      connectTimeout: 30000,      readTimeout: 30000    })    if (response.responseCode >= 200 && response.responseCode < 300) {      return JSON.parse(response.result as string) as T    } else {      throw new Error(`请求失败: ${response.responseCode}`)    }  }  get<T>(url: string): Promise<T> { return this.request<T>(url, http.RequestMethod.GET) }  post<T>(url: string, data?: object): Promise<T> { return this.request<T>(url, http.RequestMethod.POST, data) }  put<T>(url: string, data?: object): Promise<T> { return this.request<T>(url, http.RequestMethod.PUT, data) }  delete<T>(url: string): Promise<T> { return this.request<T>(url, http.RequestMethod.DELETE) }}export const httpService = new HttpService()
ViewModel里调用:
class HomeViewModel {  @State products: Product[] = []  @State loading: boolean = false  @State error: string = ''  async loadProducts() {    this.loading = true    try {      this.products = await httpService.get<Product[]>('/products')    } catch (e) {      this.error = '加载失败'    } finally {      this.loading = false    }  }}
接口怎么调、超时怎么配、错误怎么处理,都不用在每个页面重复写。
说在最后
上面这四个问题,是鸿蒙开发里绕不开的核心内容。把这几个搞透了,后面的项目开发会顺畅很多。
如果你现在还在自己摸索,文档东看一点西看一点,没有系统化的学习路径,我把我这些年整理的学习资料分享出来。
  1. 《鸿蒙开发学习包》,里面包含:
  2. ArkTS核心语法笔记(PDF)
  3. 状态管理完整解析(含踩坑记录)
  4. 项目结构模板(可直接拷贝使用)
  5. 面试高频题库(含参考答案)
  6. 我自己录的基础视频课(20+节)
当时整理这份资料,是为了方便自己上课用。后来发现很多学员在外面找的资料要么太旧、要么太散,干脆整理成了一套完整的东西。
想领取的话,私信回复「学习包」,我看到会发链接。有问题也可以直接问我,做了这么多年培训,帮你避几个坑还是做得到的。

最新文章

随机文章