知识点全集

孜航 19 阅读

课程表应用 — 涉及的全部知识点

本文档列出这道题涉及的所有 ArkTS / ArkUI 知识点,包括装饰器、组件、布局、样式、事件、状态管理、数据模型等。


一、装饰器(Decorators)

1.1 @Entry

@Entry
@Component
struct Index { ... }
  • 标记当前 struct 为页面的入口组件
  • 一个页面只能有一个 @Entry
  • 必须和 @Component 一起使用
  • 相当于 Android 的 Activity 或 Web 的 index.html

1.2 @Component

@Component
struct Index { ... }
  • 标记当前 struct 为一个自定义组件
  • 所有自定义组件必须加 @Component
  • 组件内必须有 build() 方法描述 UI

1.3 @State

@State currentDayIndex: number = 0
@State courseData: CourseDay[] = []
@State isShowDeleteDialog: boolean = false
@State deletingCourse: CourseItem | null = null
  • 状态装饰器,标记组件内部的状态变量
  • @State 变量的值发生变化时,自动触发 UI 重新渲染
  • 这是 ArkUI 响应式编程的核心机制
  • 支持的类型:numberstringboolean、数组、对象、null

1.4 @Builder

@Builder buildWeekNavigation() { ... }
@Builder buildCourseList() { ... }
@Builder buildCourseItem(course: CourseItem, index: number) { ... }
  • 构建器装饰器,用于定义可复用的 UI 构建函数
  • 相当于把一段 UI 封装成一个方法,在 build() 中通过 this.xxx() 调用
  • 可以带参数(如 buildCourseItem(course, index)
  • 作用:拆分复杂 UI,提高代码可读性和复用性

二、生命周期

2.1 aboutToAppear()

aboutToAppear() {
  this.initCourseData()
}
  • 组件即将显示时调用的生命周期钩子
  • build() 之前执行
  • 适合做数据初始化操作
  • 常见生命周期顺序:aboutToAppear()build()aboutToDisappear()

三、布局组件

3.1 Column — 垂直布局

Column() {
  // 子组件从上到下排列
  Text('标题')
  Text('内容')
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
.padding(16)
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
  • 子组件垂直方向从上到下排列
  • 常用属性:
    • .justifyContent(FlexAlign.Center) — 垂直居中
    • .alignItems(HorizontalAlign.Center) — 水平居中
    • .layoutWeight(1) — 占据父容器剩余空间

3.2 Row — 水平布局

Row() {
  // 子组件从左到右排列
  Text('左')
  Text('右')
}
  • 子组件水平方向从左到右排列
  • 本题用于:时间标签和课程信息的水平排列

3.3 Scroll — 滚动容器

Scroll() {
  Row() { ... }
}
.scrollable(ScrollDirection.Horizontal)
  • 让子组件可以滚动显示
  • .scrollable(ScrollDirection.Horizontal) — 水平滚动
  • .scrollable(ScrollDirection.Vertical) — 垂直滚动(默认)
  • 本题用于:星期导航的水平滚动,一周 7 天超出屏幕宽度时可以左右滑动

3.4 List + ListItem — 列表

List({ space: 10 }) {
  ForEach(this.data, (item: CourseItem, index: number) => {
    ListItem() {
      this.buildCourseItem(item, index)
    }
  }, (item: CourseItem) => item.id)
}
.layoutWeight(1)
  • List 是列表容器,space: 10 设置列表项间距
  • ListItem 是列表中的每一项
  • 支持滚动、分隔线等列表特性
  • Column + ForEach 更适合长列表(有懒加载优化)

四、基础组件

4.1 Text — 文本

Text('我的课程表')
  .fontSize(24)
  .fontWeight(FontWeight.Bold)  // 或 900
  .fontColor('#000000')
  .margin({ top: 20, bottom: 10 })
  • 显示文本内容
  • 常用属性:
属性作用示例
.fontSize()字体大小.fontSize(24)
.fontWeight()字体粗细.fontWeight(FontWeight.Bold).fontWeight(900)
.fontColor()字体颜色.fontColor('#000000')
.margin()外边距.margin({ top: 20, bottom: 10 })
  • 字体粗细值:FontWeight.Lighter(100-300)、FontWeight.Normal(400-500)、FontWeight.Medium(500-600)、FontWeight.Bold(600-900),也可以直接写数字

五、循环渲染 — ForEach

5.1 基本用法

ForEach(
  arr,                    // 数据源数组
  (item, index) => { ... },  // 渲染函数
  (item) => item.id          // 键值生成器(可选但推荐)
)
  • 遍历数组,为每个元素生成对应的 UI 组件
  • 三个参数:
    1. 数据源:要遍历的数组
    2. 渲染函数(item, index) => { ... },item 是当前元素,index 是索引
    3. 键值生成器:返回唯一标识字符串,用于 diff 算法优化

5.2 本题的两处 ForEach

星期导航(遍历一周数据):

ForEach(this.courseData, (dayItem: CourseDay, index: number) => {
  Column() { ... }
})

课程列表(遍历当天课程):

ForEach(this.courseData[this.currentDayIndex].courses, (course: CourseItem, index: number) => {
  ListItem() { ... }
}, (course: CourseItem) => course.id)

六、条件渲染

6.1 if / else

Column() {
  if (this.courseData[this.currentDayIndex].courses.length > 0) {
    List({ space: 10 }) { ... }
  } else {
    Column() {
      Text('📚')
      Text('今天没有课程,好好休息吧!')
    }
  }
}
  • build() 中使用 if/else 根据条件渲染不同的 UI
  • 条件表达式的结果为 true 渲染 if 分支,false 渲染 else 分支
  • 本题用于:有课程时显示列表,无课程时显示空状态

七、样式属性大全

7.1 尺寸

属性作用示例
.width()宽度.width('100%').width(200)
.height()高度.height('100%').height(50)
.layoutWeight()弹性布局权重.layoutWeight(1) 占据剩余空间

7.2 间距

属性作用示例
.padding()内边距.padding(16).padding({ left: 16, right: 16, top: 12, bottom: 12 })
.margin()外边距.margin({ top: 20, bottom: 10 }).margin({ right: 8 })
  • padding 是组件内部的空白(边框到内容之间)
  • margin 是组件外部的空白(边框到其他组件之间)

7.3 背景和边框

属性作用示例
.backgroundColor()背景色.backgroundColor('#F5F5F5')
.borderRadius()圆角.borderRadius(12).borderRadius(20)

7.4 阴影

.shadow({
  radius: 2,          // 模糊半径
  color: '#1A000000',  // 阴影颜色(带透明度)
  offsetX: 0,          // X 轴偏移
  offsetY: 1           // Y 轴偏移
})
  • color 的前两位 1A 是透明度(十六进制,1A = 约 10% 不透明度)
  • 阴影让卡片有"浮起来"的视觉效果

7.5 对齐

属性作用取值
.justifyContent()主轴对齐FlexAlign.StartFlexAlign.CenterFlexAlign.EndFlexAlign.SpaceBetween
.alignItems()交叉轴对齐HorizontalAlign.StartHorizontalAlign.CenterHorizontalAlign.End
  • Column 中主轴是垂直方向justifyContent(FlexAlign.Center) 是垂直居中
  • Column 中交叉轴是水平方向alignItems(HorizontalAlign.Center) 是水平居中

八、事件处理

8.1 onClick — 点击事件

.onClick(() => {
  this.currentDayIndex = index
})
  • 组件被点击时触发
  • 回调函数中可以修改 @State 变量,触发 UI 更新

8.2 PanGesture — 手势

.gesture(
  PanGesture({
    direction: PanDirection.Left,  // 方向:左滑
    distance: 50                   // 滑动距离阈值(vp)
  })
    .onActionEnd(() => {
      this.deletingCourse = course
      this.showDeleteConfirm()
    })
)
  • PanGesture 是拖拽/滑动手势
  • direction:滑动方向
    • PanDirection.Left — 左滑
    • PanDirection.Right — 右滑
    • PanDirection.Up — 上滑
    • PanDirection.Down — 下滑
  • distance:触发手势的最小滑动距离(单位 vp)
  • .onActionEnd():手势结束时触发的回调

九、对话框 — AlertDialog

9.1 课程详情对话框(单按钮)

AlertDialog.show({
  title: course.name,
  message: `⏰ 时间: ${course.time}\n🏫 教室: ${course.classroom}\n👨‍🏫 教师: ${course.teacher}`,
  confirm: {
    value: '确定',
    action: () => {}
  },
  alignment: DialogAlignment.Center
})

9.2 删除确认对话框(双按钮)

AlertDialog.show({
  title: '删除课程',
  message: `确定要删除"${this.deletingCourse.name}"课程吗?`,
  primaryButton: {
    value: '取消',
    action: () => { this.deletingCourse = null }
  },
  secondaryButton: {
    value: '删除',
    action: () => { this.deleteCourse() }
  },
  alignment: DialogAlignment.Center
})
  • AlertDialog.show() 显示一个模态对话框
  • 参数说明:
参数作用
title对话框标题
message对话框内容(支持模板字符串)
confirm单按钮模式(详情对话框用)
primaryButton主按钮(通常是"取消")
secondaryButton次按钮(通常是"确认")
alignment对话框位置,DialogAlignment.Center 居中
  • \n 在 message 中表示换行

十、数据模型 — class

10.1 CourseDay 类

class CourseDay {
  day: string = ''
  date: string = ''
  courses: CourseItem[] = []
}

10.2 CourseItem 类

class CourseItem {
  id: string = ''
  name: string = ''
  time: string = ''
  classroom: string = ''
  teacher: string = ''
}
  • 使用 class 定义数据模型
  • 每个字段有类型和默认值
  • CourseItem[] 表示 CourseItem 类型的数组

十一、TypeScript / ArkTS 语法

11.1 类型声明

@State currentDayIndex: number = 0
@State courseData: CourseDay[] = []
@State deletingCourse: CourseItem | null = null
  • number — 数字类型
  • string — 字符串类型
  • boolean — 布尔类型
  • CourseDay[] — 数组类型
  • CourseItem | null — 联合类型(可以是 CourseItem 或 null)

11.2 模板字符串

`⏰ 时间: ${course.time}\n🏫 教室: ${course.classroom}\n👨‍🏫 教师: ${course.teacher}`
  • 用反引号 ` 包裹
  • ${expression} 插入变量或表达式
  • \n 换行符

11.3 字符串方法

course.time.split('-')[0]   // "08:00-09:40" → "08:00"
course.time.split('-')[1]   // "08:00-09:40" → "09:40"
  • split(separator) 按分隔符拆分字符串,返回数组
  • [0] 取第一个元素,[1] 取第二个元素

11.4 数组方法

// findIndex — 查找元素索引
const index = currentDayCourses.findIndex(course => course.id === this.deletingCourse!.id)

// splice — 删除元素
this.courseData[this.currentDayIndex].courses.splice(index, 1)

// JSON 深拷贝 — 触发 UI 更新
this.courseData = JSON.parse(JSON.stringify(this.courseData))
方法作用返回值
findIndex()查找满足条件的元素索引找到返回索引,找不到返回 -1
splice(index, 1)从 index 位置删除 1 个元素被删除的元素(本题不用)
JSON.parse(JSON.stringify(obj))深拷贝对象新对象,引用地址不同

为什么需要 JSON 深拷贝?
@State 检测变化是通过引用比较的。splice 修改的是原数组的内容,但数组引用没变,@State 不会触发 UI 更新。深拷贝生成一个新数组赋值回去,引用变了,UI 就更新了。

11.5 非空断言

this.deletingCourse!.id
  • ! 是非空断言操作符
  • 告诉编译器"我确定这个值不是 null/undefined"
  • 本题中 deletingCourse 类型是 CourseItem | null,用 ! 断言它不为 null

11.6 箭头函数

() => { this.currentDayIndex = index }
(course: CourseItem) => course.id
(dayItem: CourseDay, index: number) => { ... }
  • () => expression — 无参箭头函数
  • (param) => expression — 带参箭头函数
  • () => { statements } — 多行箭头函数体

11.7 三元表达式

index === this.currentDayIndex ? '#FFFFFF' : '#666666'
  • 条件 ? 值1 : 值2
  • 条件为 true 返回值1,否则返回值2
  • 本题大量用于:选中/未选中状态的样式切换

十二、颜色规范

本题使用的颜色体系(蓝色主题):

颜色值用途含义
#007DFF选中状态背景、时间文字主题蓝
#E6F2FF时间标签背景浅蓝
#F5F5F5页面背景浅灰
#FFFFFF卡片背景、选中文字白色
#000000标题文字黑色
#333333课程名称深灰
#666666辅助信息中灰
#999999次要信息浅灰
#1A000000阴影10% 黑色

颜色格式:#RRGGBB(红绿蓝)或 #AARRGGBB(透明度+红绿蓝)


十三、完整代码结构图

@Entry @Component struct Index
├── @State 状态变量 × 4
├── aboutToAppear()          ← 生命周期,调用 initCourseData
├── initCourseData()         ← 初始化 7 天课程数据
├── build()                  ← 主界面
│   ├── Text("我的课程表")    ← 标题
│   ├── buildWeekNavigation() ← @Builder 星期导航
│   │   ├── Scroll           ← 水平滚动容器
│   │   ├── Row              ← 水平布局
│   │   └── ForEach          ← 遍历 courseData
│   │       └── Column       ← 每个星期项
│   │           ├── Text(day)  ← 星期几
│   │           ├── Text(date) ← 日期
│   │           └── onClick    ← 切换选中
│   └── buildCourseList()    ← @Builder 课程列表
│       ├── if (有课程)
│       │   ├── List         ← 列表容器
│       │   └── ForEach      ← 遍历当天课程
│       │       └── ListItem
│       │           └── buildCourseItem()
│       └── else (无课程)
│           └── 空状态提示
├── buildCourseItem()        ← @Builder 单个课程项
│   ├── Row
│   │   ├── Column (时间标签)
│   │   │   ├── Text(开始时间)
│   │   │   ├── Text(|)
│   │   │   └── Text(结束时间)
│   │   └── Column (课程信息)
│   │       ├── Text(课程名称)
│   │       └── Text(教室 | 教师)
│   ├── PanGesture           ← 左滑删除手势
│   └── onClick              ← 点击查看详情
├── showCourseDetail()       ← 课程详情 AlertDialog
├── showDeleteConfirm()      ← 删除确认 AlertDialog
└── deleteCourse()           ← 删除课程并更新 UI

class CourseDay              ← 数据模型:一天
├── day: string
├── date: string
└── courses: CourseItem[]

class CourseItem             ← 数据模型:一门课
├── id: string
├── name: string
├── time: string
├── classroom: string
└── teacher: string

十四、知识点速查索引

类别知识点对应填空
装饰器@Entry, @Component, @State, @Builder空 1
生命周期aboutToAppear空 2
数据模型class 定义空 14(底部)
布局Column, Row空 4, 6, 12
滚动Scroll, ScrollDirection.Horizontal空 9
列表List, ListItem空 10
循环ForEach + 键值生成器空 5, 10
条件if / else空 10
文本Text + fontSize/fontWeight/fontColor空 1, 6, 12
样式margin, padding, backgroundColor, borderRadius, shadow空 4, 7, 13
对齐justifyContent, alignItems, layoutWeight空 4, 11
点击onClick空 8
手势PanGesture, direction, distance, onActionEnd空 13
对话框AlertDialog.show (单按钮/双按钮)空 14
类型number, string, boolean, 数组, 联合类型空 1
字符串split(), 模板字符串空 3, 12, 14
数组findIndex(), splice(), JSON 深拷贝空 14
运算三元表达式, 非空断言(!)空 6, 7, 14
函数箭头函数空 5, 8, 13