鸿蒙OS ArkTS+ArkUI 从入门到精通
1. 开发环境搭建
首先需要安装DevEco Studio开发工具:
- 访问华为开发者网站下载最新版DevEco Studio
- 安装过程中选择"自定义安装",确保勾选"模拟器"组件
- 安装完成后启动DevEco Studio,配置JDK和SDK路径
2. 第一个鸿蒙应用:Hello World
下面是一个最基础的鸿蒙应用代码,使用ArkTS语言编写:
// pages/Index.ets
import router from '@ohos.router';
@Entry // 标记为应用入口页面
@Component // 声明为组件
struct Index {
build() { // 组件构建函数
Column() { // 创建垂直布局容器
Text('Hello World') // 创建文本组件
.fontSize(50) // 设置字体大小
.fontWeight(FontWeight.Bold) // 设置字体加粗
.margin({ top: 100 }) // 设置顶部边距
Button('点击跳转') // 创建按钮组件
.margin({ top: 50 }) // 设置顶部边距
.onClick(() => { // 绑定点击事件
router.pushUrl({ // 路由跳转
url: 'pages/Second' // 目标页面路径
})
})
}
.width('100%') // 设置容器宽度为100%
.height('100%') // 设置容器高度为100%
.backgroundColor('#F5F5F5') // 设置背景颜色
}
}
这个代码创建了一个简单的页面,包含一个标题和一个按钮。按钮点击后会跳转到另一个页面。
3. 鸿蒙UI组件基础
鸿蒙提供了丰富的UI组件,下面是一个综合示例:
// pages/ComponentsDemo.ets
import router from '@ohos.router';
@Entry
@Component
struct ComponentsDemo {
@State message: string = '组件演示'; // 声明响应式状态变量
@State count: number = 0; // 声明计数器变量
build() {
Column() {
// 标题区域
Text(this.message)
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ top: 20 })
// 文本输入框
TextField({
placeholder: '请输入文本',
onInput: (value: string) => { // 绑定输入事件
this.message = value; // 更新状态变量
}
})
.width('80%')
.margin({ top: 20 })
// 图片组件
Image($r('app.media.sample')) // 加载应用资源中的图片
.width(200)
.height(200)
.objectFit(ImageFit.Contain) // 设置图片适应方式
.margin({ top: 20 })
// 开关组件
Switch({
isOn: this.count % 2 === 0, // 根据计数器值设置开关状态
onChange: (isOn: boolean) => { // 绑定状态变化事件
this.count = isOn ? this.count + 1 : this.count - 1;
}
})
.margin({ top: 20 })
// 列表组件
List() {
ForEach([1, 2, 3, 4, 5], (item: number) => { // 循环创建列表项
ListItem() {
Text(`列表项 ${item}`)
.fontSize(20)
.width('100%')
.height(50)
.textAlign(TextAlign.Center)
}
.backgroundColor(item % 2 === 0 ? '#E0E0E0' : '#FFFFFF')
})
}
.width('90%')
.height(200)
.margin({ top: 20 })
// 按钮组
Row() {
Button('增加计数')
.onClick(() => { // 绑定点击事件
this.count++; // 增加计数器值
})
Button('重置')
.onClick(() => { // 绑定点击事件
this.count = 0; // 重置计数器
this.message = '组件演示'; // 重置文本
})
}
.width('80%')
.justifyContent(FlexAlign.SpaceAround) // 水平均匀分布
.margin({ top: 20 })
// 显示计数结果
Text(`当前计数: ${this.count}`)
.fontSize(25)
.margin({ top: 20 })
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
.padding(20) // 设置内边距
.alignItems(HorizontalAlign.Center) // 水平居中对齐
}
}
以上展示了鸿蒙中常见的UI组件使用方法,包括文本输入框、图片、开关、列表和按钮等。
4. 状态管理与事件处理
鸿蒙应用中使用@State
装饰器实现响应式状态管理:
// pages/TodoList.ets
import router from '@ohos.router';
// 定义待办事项数据结构
interface TodoItem {
id: number;
text: string;
completed: boolean;
}
@Entry
@Component
struct TodoList {
@State todos: TodoItem[] = [ // 声明待办事项列表状态
{ id: 1, text: '学习鸿蒙开发', completed: false },
{ id: 2, text: '完成示例项目', completed: false },
{ id: 3, text: '提交应用', completed: false }
];
@State newTodoText: string = ''; // 声明新待办事项文本状态
@State filter: 'all' | 'active' | 'completed' = 'all'; // 声明筛选状态
// 添加新待办事项方法
addTodo() {
if (this.newTodoText.trim() === '') return;
const newTodo: TodoItem = {
id: Date.now(), // 使用时间戳作为ID
text: this.newTodoText,
completed: false
};
this.todos = [...this.todos, newTodo]; // 更新待办事项列表
this.newTodoText = ''; // 清空输入框
}
// 切换待办事项完成状态方法
toggleTodo(id: number) {
this.todos = this.todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
);
}
// 删除待办事项方法
deleteTodo(id: number) {
this.todos = this.todos.filter(todo => todo.id !== id);
}
// 获取筛选后的待办事项
getFilteredTodos() {
if (this.filter === 'active') {
return this.todos.filter(todo => !todo.completed);
} else if (this.filter === 'completed') {
return this.todos.filter(todo => todo.completed);
}
return this.todos;
}
build() {
Column() {
// 标题
Text('待办事项列表')
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ top: 20 })
// 输入区域
Row() {
TextField({
placeholder: '添加新待办事项',
onInput: (value: string) => {
this.newTodoText = value;
}
})
.width('70%')
Button('添加')
.onClick(() => this.addTodo()) // 绑定添加方法
.width('25%')
}
.width('90%')
.margin({ top: 20 })
// 筛选按钮组
Row() {
['全部', '未完成', '已完成'].forEach((label, index) => {
const filterValue = ['all', 'active', 'completed'][index];
Button(label)
.backgroundColor(this.filter === filterValue ? '#4CAF50' : '#FFFFFF')
.fontColor(this.filter === filterValue ? '#FFFFFF' : '#000000')
.onClick(() => {
this.filter = filterValue as 'all' | 'active' | 'completed';
})
})
}
.width('90%')
.justifyContent(FlexAlign.SpaceAround)
.margin({ top: 20 })
// 待办事项列表
List() {
ForEach(this.getFilteredTodos(), (todo: TodoItem) => {
ListItem() {
Row() {
Checkbox({
isChecked: todo.completed,
onChange: () => this.toggleTodo(todo.id) // 绑定切换状态方法
})
Text(todo.text)
.fontSize(20)
.fontColor(todo.completed ? '#9E9E9E' : '#000000')
.strikethrough(todo.completed) // 已完成的任务添加删除线
Button('删除')
.backgroundColor('#F44336')
.fontColor('#FFFFFF')
.onClick(() => this.deleteTodo(todo.id)) // 绑定删除方法
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
}
.backgroundColor(todo.id % 2 === 0 ? '#E0E0E0' : '#FFFFFF')
})
}
.width('90%')
.height(300)
.margin({ top: 20 })
// 统计信息
Text(`总共: ${this.todos.length},已完成: ${this.todos.filter(t => t.completed).length}`)
.fontSize(20)
.margin({ top: 20 })
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
.padding(20)
.alignItems(HorizontalAlign.Center)
}
}
以上示例实现了一个完整的待办事项应用,包含添加、删除、标记完成和筛选等功能,展示了鸿蒙应用中状态管理和事件处理的实践。
5. 页面路由与导航
鸿蒙应用中使用router模块实现页面间的导航:
// pages/Index.ets
import router from '@ohos.router';
@Entry
@Component
struct Index {
build() {
Column() {
Text('多页面应用示例')
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ top: 50 })
Button('查看商品列表')
.margin({ top: 50 })
.onClick(() => {
router.pushUrl({
url: 'pages/Products',
params: { category: 'phones' } // 传递参数
});
})
Button('用户信息')
.margin({ top: 20 })
.onClick(() => {
router.pushUrl({
url: 'pages/UserInfo',
params: { userId: 123 } // 传递参数
});
})
Button('设置')
.margin({ top: 20 })
.onClick(() => {
router.pushUrl({ url: 'pages/Settings' });
})
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
.alignItems(HorizontalAlign.Center)
}
}
// pages/Products.ets
import router from '@ohos.router';
@Entry
@Component
struct Products {
@Link category: string = ''; // 接收传递的参数
build() {
Column() {
// 返回按钮
Button('返回')
.margin({ top: 20, left: 20 })
.onClick(() => {
router.back(); // 返回上一页
})
Text(`商品列表 - ${this.category}`)
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ top: 30 })
// 模拟商品列表
List() {
ForEach([1, 2, 3, 4, 5], (index: number) => {
ListItem() {
Column() {
Image($r('app.media.sample')) // 使用示例图片
.width('100%')
.height(150)
.objectFit(ImageFit.Cover)
Text(`商品 ${index}`)
.fontSize(20)
.margin({ top: 10 })
Text('¥999.00')
.fontSize(18)
.fontColor('#FF5722')
.margin({ top: 5 })
}
.width('100%')
.padding(10)
.backgroundColor(index % 2 === 0 ? '#E0E0E0' : '#FFFFFF')
.onClick(() => {
router.pushUrl({
url: 'pages/ProductDetail',
params: { productId: index }
});
})
}
})
}
.width('90%')
.height('70%')
.margin({ top: 20 })
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
}
// pages/ProductDetail.ets
import router from '@ohos.router';
@Entry
@Component
struct ProductDetail {
@Link productId: number = 0; // 接收传递的参数
build() {
Column() {
// 返回按钮
Button('返回')
.margin({ top: 20, left: 20 })
.onClick(() => {
router.back();
})
Text(`商品详情 - ${this.productId}`)
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ top: 30 })
Image($r('app.media.sample')) // 使用示例图片
.width('90%')
.height(300)
.objectFit(ImageFit.Cover)
.margin({ top: 20 })
Text('高级智能手机')
.fontSize(25)
.margin({ top: 20, left: 20 })
Text('¥999.00')
.fontSize(30)
.fontColor('#FF5722')
.margin({ top: 10, left: 20 })
Text('这是一款功能强大的智能手机,具有高清屏幕、超长续航和顶级相机系统。')
.fontSize(18)
.margin({ top: 20, left: 20, right: 20 })
Button('加入购物车')
.width('90%')
.height(60)
.backgroundColor('#FF5722')
.fontColor('#FFFFFF')
.fontSize(20)
.margin({ top: 30 })
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
}
这个示例展示了如何在鸿蒙应用中实现多页面导航,包括页面间的参数传递和返回功能。
6. 网络请求与数据处理
鸿蒙应用中可以使用fetch API进行网络请求:
// pages/NewsList.ets
import router from '@ohos.router';
import http from '@ohos.net.http';
@Entry
@Component
struct NewsList {
@State newsList: Array<{ title: string; content: string; time: string }> = [];
@State isLoading: boolean = true;
@State errorMessage: string = '';
aboutToAppear() {
this.fetchNews(); // 页面加载时获取新闻数据
}
// 获取新闻数据方法
fetchNews() {
this.isLoading = true;
this.errorMessage = '';
// 创建HTTP请求
let httpRequest = http.createHttp();
// 配置请求参数
let requestOptions = {
method: http.RequestMethod.GET,
readTimeout: 60000,
connectTimeout: 60000,
header: {
'Content-Type': 'application/json'
}
};
// 发送请求
httpRequest.request(
'https://api.example.com/news', // 示例API地址
requestOptions,
(err, response) => {
if (err) {
this.errorMessage = '获取新闻失败: ' + err.message;
this.isLoading = false;
return;
}
if (response.responseCode === 200) {
try {
// 解析响应数据
const result = JSON.parse(response.result.toString());
this.newsList = result.data || [];
} catch (e) {
this.errorMessage = '解析数据失败';
}
} else {
this.errorMessage = '服务器返回错误: ' + response.responseCode;
}
this.isLoading = false;
}
);
}
build() {
Column() {
// 返回按钮
Button('返回')
.margin({ top: 20, left: 20 })
.onClick(() => {
router.back();
})
Text('新闻列表')
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ top: 30 })
// 加载状态显示
if (this.isLoading) {
Column() {
Text('加载中...')
.fontSize(20)
ProgressBar() // 进度条组件
.width('50%')
.color('#4CAF50')
.margin({ top: 20 })
}
.width('100%')
.height('50%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
// 错误信息显示
if (this.errorMessage) {
Text(this.errorMessage)
.fontSize(20)
.fontColor('#F44336')
.margin({ top: 20 })
.onClick(() => this.fetchNews()) // 点击重试
}
// 新闻列表显示
if (!this.isLoading && !this.errorMessage && this.newsList.length > 0) {
List() {
ForEach(this.newsList, (news, index) => {
ListItem() {
Column() {
Text(news.title)
.fontSize(22)
.fontWeight(FontWeight.Bold)
.margin({ top: 10 })
Text(news.content.length > 100 ? news.content.substring(0, 100) + '...' : news.content)
.fontSize(18)
.margin({ top: 10 })
Text(news.time)
.fontSize(16)
.fontColor('#757575')
.margin({ top: 10 })
}
.width('100%')
.padding(15)
.backgroundColor(index % 2 === 0 ? '#E0E0E0' : '#FFFFFF')
}
})
}
.width('90%')
.height('70%')
.margin({ top: 20 })
}
// 空列表显示
if (!this.isLoading && !this.errorMessage && this.newsList.length === 0) {
Text('暂无新闻')
.fontSize(20)
.margin({ top: 20 })
}
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
}
以上展示了如何在鸿蒙应用中进行网络请求,处理加载状态和错误情况,并将获取的数据展示在界面上。
7. 鸿蒙组件化开发
鸿蒙应用鼓励组件化开发,组件复用的示例:
// components/MyButton.ets
@Component
struct MyButton {
@Link text: string = '按钮'; // 接收外部传入的文本
@Link onClick: () => void = () => {}; // 接收外部传入的点击回调
build() {
Button(this.text)
.width('80%')
.height(50)
.backgroundColor('#4CAF50')
.fontColor('#FFFFFF')
.fontSize(18)
.onClick(() => {
this.onClick(); // 触发外部传入的回调
})
}
}
// components/MyCard.ets
@Component
struct MyCard {
@Link title: string = '标题';
@Link content: string = '内容';
@Link imageSource: ResourceStr = $r('app.media.sample');
build() {
Stack() {
// 卡片背景
Rectangle()
.width('90%')
.height(200)
.radius(10)
.fill('#FFFFFF')
.shadow({
offsetX: 2,
offsetY: 2,
blurRadius: 10,
color: '#888888'
})
// 卡片内容
Column() {
Image(this.imageSource)
.width('100%')
.height(120)
.objectFit(ImageFit.Cover)
.borderRadius({ topLeft: 10, topRight: 10 })
Text(this.title)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ top: 10, left: 10 })
.width('90%')
.maxLines(1)
.overflow(TextOverflow.Ellipsis)
Text(this.content)
.fontSize(16)
.margin({ top: 5, left: 10, right: 10 })
.width('90%')
.maxLines(1)
.overflow(TextOverflow.Ellipsis)
}
.width('90%')
}
.width('100%')
.height(200)
.margin({ top: 20 })
}
}
// pages/ComponentDemo.ets
import router from '@ohos.router';
import { MyButton } from '../components/MyButton';
import { MyCard } from '../components/MyCard';
@Entry
@Component
struct ComponentDemo {
@State count: number = 0;
increment() {
this.count++;
}
build() {
Column() {
// 返回按钮
Button('返回')
.margin({ top: 20, left: 20 })
.onClick(() => {
router.back();
})
Text('组件复用演示')
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ top: 30 })
// 使用自定义按钮组件
MyButton({
text: '点击增加',
onClick: () => this.increment()
})
.margin({ top: 20 })
// 显示计数
Text(`计数: ${this.count}`)
.fontSize(25)
.margin({ top: 20 })
// 使用自定义卡片组件
MyCard({
title: '新闻标题1',
content: '这是一条重要的新闻内容,包含了最新的科技动态。',
imageSource: $r('app.media.sample')
})
MyCard({
title: '新闻标题2',
content: '另一条新闻内容,讨论了人工智能的发展前景。',
imageSource: $r('app.media.sample')
})
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
}
可复用的组件,并在不同的页面中使用它们,提高代码的可维护性和复用性。
8. 学习建议
- 首先熟悉ArkTS语言的基础语法,特别是装饰器和响应式编程的概念
- 掌握鸿蒙UI组件的使用方法,了解各种布局容器和控件
- 学习状态管理和事件处理,这是构建交互应用的基础
- 多做练习,尝试实现各种功能,从简单到复杂
- 参考官方文档和示例代码,华为开发者网站提供了丰富的学习资源
- 进阶参考文献《鸿蒙 ArkTS 实战!手把手复刻微信全功能页面(含底部导航 / 聊天列表 / 通讯录)》