摘要

本文基于HarmonyOS ArkTS(ArkUI声明式开发范式)从零搭建极简天气预报应用,全程使用@Entry@Component自定义组件、@State响应式状态管理三大核心装饰器,实现城市名称展示、实时温度渲染、随机切换天气功能。适合大一鸿蒙入门开发者快速上手,拆解ArkUI页面生命周期、状态驱动UI、点击事件回调、随机数据生成等基础知识点,代码可直接复制运行,附带每段代码逐行注释与原理讲解。

关键词:HarmonyOS;ArkTS;ArkUI;状态管理;移动端App开发

一、引言

在鸿蒙应用开发体系中,ArkUI作为官方主推的声明式UI框架,区别于传统Android XML布局、iOS Storyboard的命令式写法,采用数据驱动视图的核心理念:数据一旦变更,页面UI自动刷新,无需手动操作控件刷新方法。

@State是ArkUI最基础、使用频率最高的状态装饰器,被标记的变量具备响应式能力;@Entry标识页面入口组件,一个应用页面有且仅有一个入口;@Component用来封装复用子组件,实现代码解耦。

本次实战制作轻量天气预报App,业务逻辑极简但覆盖入门全部核心语法:静态文本渲染、状态变量绑定、Button点击事件、Math随机函数生成天气与温度,吃透本案例能快速建立ArkTS基础编码思维,对后续网络请求真实天气接口、多页面跳转、列表渲染打下铺垫。很多新手刚接触时分不清装饰器作用域、this指向、事件回调写法,本文会逐个拆解误区。

二、开发前置环境

2.1 工具版本

DevEco Studio 5.0及以上,配套HarmonyOS SDK 8/9/10均可,兼容手机模拟器、真机调试。

2.2 新建工程步骤

  1. 打开DevEco Studio → 创建项目 → 选择「ArkTS」→「空白活动」模板;
  2. 项目名称自定义(WeatherDemo),包名默认即可;
  3. 等待gradle同步、依赖自动下载完成,打开entry/src/main/ets/pages/Index.ets主页面文件,清空默认模板代码,粘贴本文示例代码。

三、完整可运行代码+逐行深度注释

// 页面入口装饰器:标记当前组件为应用启动首页,全局唯一

@Entry

// 自定义组件装饰器:所有页面/子组件必须添加,构建build渲染函数

@Component

struct WeatherApp {

  // @State响应式状态变量:变量修改后,绑定该变量的UI控件自动刷新

  // 1. 城市名称,字符串类型,默认值南昌

  @State city: string = "南昌"

  // 2. 温度数值,数字类型,初始26℃

  @State temp: number = 26

  // 3. 天气状况文本,默认晴天

  @State weather: string = "晴"

  // build()函数:ArkUI固定渲染入口,内部书写所有页面布局控件

  build() {

    // Column纵向布局容器:子元素自上而下垂直排列(类比前端flex-direction:column)

    Column() {

      // 第一行文本:展示城市名称,字号32

      Text(this.city)

        .fontSize(32)

        .margin({ bottom:10 }) // 底部外边距,拉开间距

      

      // 第二行文本:模板字符串拼接温度+天气,字号28

      Text(`${this.temp}℃ ${this.weather}`)

        .fontSize(28)

        .margin({ bottom:20 })

      // 按钮控件:绑定点击回调事件

      Button("切换天气")

        .fontSize(22)

        .width(180)

        .height(60)

        // onClick点击事件:箭头函数作为回调,点击执行内部逻辑

        .onClick(() => {

          // 定义天气数组,存放所有可选天气类型

          let arr: string[] = ["晴", "雨", "多云", "阴"]

          // Math.random()生成0~1随机小数;*4放大0~4;floor向下取整得到0/1/2/3合法下标

          this.weather = arr[Math.floor(Math.random() * 4)]

          // 温度随机区间:20~29度,基础20 + 0~9随机数

          this.temp = Math.floor(20 + Math.random() * 10)

        })

    }

    // 页面整体样式:铺满全屏、居中对齐、内边距

    .width("100%")

    .height("100%")

    .justifyContent(FlexAlign.Center)

    .padding(30)

  }

}

3.1 代码结构分层拆解

  1. 装饰器层@Entry@Component是首页标准格式;如果是子复用组件,只写@Component不能加@Entry
  2. 状态变量层:所有需要动态改变、页面实时更新的数据,必须加@State;普通let/const局部变量修改不会刷新UI;
  3. 布局容器层:Column垂直、Row水平是两大基础容器,所有控件必须包裹在容器内;
  4. UI控件层:Text文本、Button按钮是基础原子组件,链式调用.fontSize().width()属于属性修饰器;
  5. 事件逻辑层.onClick()接收回调函数,箭头函数内修改this绑定的状态变量,触发页面重绘。

四、核心知识点精讲

4.1 @State响应式原理

普通变量赋值后页面无变化:

let testNum = 1;

testNum = 2; // UI不会更新

@State修饰后,框架自动监听变量内存地址变化,一旦赋值,build里用到this.变量的组件全部重新渲染,这是ArkUI数据驱动的核心。

易错点:状态变量只能在struct结构体内部定义,不能写在build里面、不能写在函数内部。

4.2 this指向问题

在Button的onClick箭头函数中,this始终指向WeatherApp当前组件实例;如果换成普通function(){}写法,this指向会丢失,无法修改状态变量,所以鸿蒙开发事件回调统一推荐箭头函数。

错误示范(失效写法):

// 禁止这种写法,this指向异常

.onClick(function(){

  this.temp = 25

})

4.3 Math随机函数计算逻辑

  1. Math.random():返回范围 [0,1) 包含0、不包含1的浮点数;
  2. Math.floor():向下取整,舍去小数部分;

天气数组长度为4,下标0、1、2、3,Math.random()*4得到0~3.999,floor后刚好匹配数组下标;

温度公式20 + Math.random()*10:最小值20,最大值无限接近30,floor后区间20~29。

4.4 布局对齐规则

Column容器添加.justifyContent(FlexAlign.Center)实现内部所有元素垂直居中;width、height设100%占满手机屏幕宽高,适配不同分辨率设备,不用写固定像素。

五、模拟器运行效果演示

  1. 启动模拟器(手机设备),点击运行按钮;
  2. 页面顶部显示「南昌」城市名;
  3. 中间展示默认26℃ 晴;
  4. 点击切换天气按钮:
    • 天气随机在晴/雨/多云/阴轮换;
    • 温度同步随机刷新20-29区间数值;
  5. 全程无卡顿,点击瞬间UI同步刷新,验证@State响应式生效。

以下是对代码的详细解析,按功能模块划分:

5.1装饰器部分

@Entry标记当前组件为应用启动首页,全局唯一入口 @Component标识自定义组件装饰器,所有页面/子组件必须添加

5.2状态变量声明

@State city: string = "南昌"
响应式城市名称变量,默认值为"南昌",修改后自动触发UI更新
@State temp: number = 26
响应式温度数值变量,初始26℃
@State weather: string = "晴"
响应式天气状态变量,默认晴天

5.3布局构建

Column()纵向布局容器
子元素默认垂直排列,相当于CSS的flex-direction: column
.width("100%").height("100%") 设置容器宽高占满父元素
.justifyContent(FlexAlign.Center) 主轴(垂直方向)居中对齐
.padding(30) 设置内边距30单位

5.4UI控件

Text(this.city).fontSize(32)
显示城市名称的文本控件,字号32px
Text(${this.temp}℃ ${this.weather}).fontSize(28)
模板字符串拼接显示温度和天气,字号28px
Button("切换天气")
交互按钮控件,设置固定宽高180*60单位

5.5事件处理

onClick(() => {...})
按钮点击回调函数,使用箭头函数定义
Math.floor(Math.random() * 4)
生成0-3的随机整数,用于天气数组索引
Math.floor(20 + Math.random() * 10)
生成20-29区间的随机温度值

5.6数据更新机制

当修改@State修饰的变量时:

  1. 自动触发组件重新构建(build())
  2. 检查新旧VDOM差异
  3. 仅更新变化的UI部分
  4. 保持其他UI状态不变

5.7样式处理

.margin({ bottom:10 })
设置底部外边距10单位
链式调用多个样式方法,类似CSS-in-JS写法
所有尺寸单位默认使用vp(虚拟像素)

随机逻辑实现

let arr: string[] = ["晴", "雨", "多云", "阴"]
定义天气类型数组,TypeScript明确类型为字符串数组
随机索引确保不会越界访问
温度计算保证始终在20-29度范围内

5.8响应式原理

ArkUI的响应式系统:

  1. 使用@State建立数据与UI的绑定
  2. 数据变更自动触发组件更新
  3. 采用精细化的差异比对算法
  4. 仅更新必要的DOM节点

5.9代码结构特点

  1. 声明式UI编程范式
  2. 状态驱动视图更新
  3. 类型安全的TypeScript语法
  4. 链式方法调用风格
  5. 逻辑与UI高度解耦

5.10扩展建议

可增加的功能方向:

  • 网络请求获取真实天气数据
  • 城市选择下拉菜单
  • 天气图标可视化
  • 温度趋势图表
  • 多日天气预报列表

六、功能拓展升级方案(进阶自学)

6.1 拓展1:下拉刷新、增加更多城市选择

新增城市数组,添加「切换城市」按钮,复制随机逻辑更换city状态值;

6.2 拓展2:接入真实网络天气接口

使用http网络模块请求和风天气、高德开放平台免费天气API,解析JSON数据赋值给@State变量,替代本地随机假数据;

6.3 拓展3:天气图标匹配

用Image组件,判断weather文本值,不同天气展示对应晴/雨/多云图片资源;

6.4 拓展4:美化UI样式

添加背景渐变、按钮圆角、字体颜色区分高温低温、卡片阴影效果。

七、新手高频报错排查

  1. 报错:@Entry只能用于一个组件

原因:页面写了两个@Entry装饰器,删除子组件多余@Entry即可;

  1. 点击按钮页面无变化

排查:变量有没有加@State、回调是不是普通function、赋值有没有带this;

  1. 数组下标报错undefined

排查:随机乘数和数组长度必须一致,数组4个元素就4,不要写成3/*5;

  1. 样式属性标红

排查:DevEco Studio SDK版本过低,升级SDK、同步工程依赖。

八、总结

本天气预报小案例麻雀虽小五脏俱全,覆盖ArkTS入门四大基石:装饰器体系、响应式状态管理、声明式布局、点击事件交互。大一初学鸿蒙不用一上来啃复杂商城、社交大项目,从这种几十行轻量Demo练手,吃透每一行语法逻辑,再循序渐进做网络请求、路由跳转、数据库存储等复杂业务。ArkUI声明式范式上手门槛低,逻辑清晰易调试,是国产移动端开发主流技术栈,熟练后可快速迁移多端(手机、平板、智能屏)统一开发范式。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐