解题指南

孜航 16 阅读

课程表应用 — 模板补全解题指南

一、解题方法:四步拆解法

第一步:先看数据模型,搞清楚"有什么"

模板底部有 CourseDayCourseItem 两个类,字段都是空的。但注释已经告诉你每个字段的用途。先把数据模型填上,因为所有上层代码都在操作这些字段。填完之后 course.namecourse.time 这些属性就是合法的,写 UI 代码时心里有底。

这一步是很多人忽略的。一上来就看 UI 模板发懵,是因为你连数据长什么样都不知道。

第二步:看已有代码,反推缺失部分

模板不是完全空的,它留了大量线索。比如:

ForEach( //写入代码            => {

你不需要猜 ForEach 要遍历什么。往上看——buildWeekNavigation 是"星期导航构建器",courseData 是一周的数据,那遍历的肯定是 this.courseData

规律:模板里已经写出来的代码,就是你最大的提示。 已有的 .fontSize(16).borderRadius(20) 这些链式调用告诉你这是什么组件,你只需要补参数。

第三步:数注释,不要数"写入代码"

每个 //写入代码 旁边几乎都有中文注释,这不是装饰,是告诉你这里写什么。比如:

.backgroundColor(//写入代码                ) // 选中状态样式

注释说"选中状态样式",逻辑就是:选中一个颜色,没选中另一个——三元表达式。

你做的不是"从零创作",是"根据提示填空"。

第四步:参考答案只用来"验证",不要用来"背"

  1. 自己先根据注释和已有代码尝试写
  2. 写不出来再看参考答案那一行对应的是什么
  3. 理解为什么是这个写法,然后合上答案自己重写

二、14 处填空逐个拆解

填空 1:状态变量声明(第 282-286 行)

模板:

//写入代码
                // 当前选中的星期索引
                // 课程数据数组
                // 是否显示删除对话框
                // 正在删除的课程项

填入:

@State currentDayIndex: number = 0
@State courseData: CourseDay[] = []
@State isShowDeleteDialog: boolean = false
@State deletingCourse: CourseItem | null = null

思路: 注释直接告诉你四个变量名和用途,@State 是 ArkTS 状态装饰器,类型根据注释推断。


填空 2:aboutToAppear 调用(第 289-291 行)

模板:

aboutToAppear() {
  //写入代码
            // 组件出现时初始化课程数据
}

填入:

this.initCourseData()

思路: 注释说"初始化课程数据",下面已经定义了 initCourseData() 方法,调用它就行。


填空 3:initCourseData 数据填充(第 297-301 行)

模板:

initCourseData() {
  this.courseData = [// 初始化一周的课程数据

      //写入代码

  ]
}

填入: 参考答案第 17-68 行的完整数组内容,即 7 天的课程数据。结构如下:

{
  day: '周一',
  date: '12月25日',
  courses: [
    { id: '1', name: '高等数学', time: '08:00-09:40', classroom: '教学楼A201', teacher: '张教授' },
    { id: '2', name: '大学英语', time: '10:00-11:40', classroom: '外语楼B101', teacher: '李老师' },
    { id: '3', name: '计算机基础', time: '14:00-15:40', classroom: '实验楼C301', teacher: '王教授' }
  ]
},
// ... 周二到周日,参考答案完整数据

思路: 字段名和数据模型 CourseDayCourseItem 对应。数据内容直接从参考答案搬。


填空 4:build 主界面补全(第 307-320 行)

模板:

build() {
  Column() {
    //写入代码
        // 顶部标题
        Text("我的课程表").fontSize(24).fontWeight(900).fontColor('#000000')
        // 星期导航
    this.buildWeekNavigation()
         // 课程列表区域
  }
          // 宽度100%
          // 高度100%
          // 背景色
           // 内边距
}

填入:

标题后面加 margin:

.margin({ top: 20, bottom: 10 })

星期导航和课程列表之间加:

this.buildWeekNavigation()
this.buildCourseList()

Column 属性链(注释已经告诉你每个属性是什么):

.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
.padding(16)

思路: 注释已经列出了每个属性的含义,直接按注释写属性值。


填空 5:ForEach 参数(第 328 行)

模板:

ForEach( //写入代码            => {

填入:

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

思路: buildWeekNavigation 是星期导航,遍历的是一周数据 this.courseData,回调参数是每一天的数据项和索引。


填空 6:星期导航内部 Text(第 330-337 行)

模板:

Column() {
//写入代码
}

填入:

Text(dayItem.day)
  .fontSize(16)
  .fontColor(index === this.currentDayIndex ? '#FFFFFF' : '#666666')
Text(dayItem.date)
  .fontSize(12)
  .fontColor(index === this.currentDayIndex ? '#FFFFFF' : '#999999')
  .margin({ top: 2 })

思路: 星期导航要显示"星期"和"日期"两行文字,选中时白色、未选中时灰色。三元表达式判断 index === this.currentDayIndex


填空 7:选中状态背景色(第 340 行)

模板:

.backgroundColor(//写入代码                ) // 选中状态样式

填入:

.backgroundColor(index === this.currentDayIndex ? '#007DFF' : '#FFFFFF')

思路: 注释说"选中状态样式",选中蓝色 #007DFF,未选中白色 #FFFFFF


填空 8:onClick 更新索引(第 343 行)

模板:

.onClick(() => {
        //写入代码             // 更新选中状态
})

填入:

this.currentDayIndex = index

思路: 注释说"更新选中状态",点击哪个就把它设为当前选中。


填空 9:scrollable 方向(第 350 行)

模板:

.scrollable( //写入代码)  // 设置水平滚动

填入:

.scrollable(ScrollDirection.Horizontal)

思路: 注释说"水平滚动",枚举值就是 ScrollDirection.Horizontal


填空 10:课程列表 ForEach(第 356-362 行)

模板:

if ( //写入代码  ) {
  List({ space: 10 }) {
    ForEach(//写入代码   ) => {
      ListItem() {
        this.buildCourseItem(course, index)
      }
    }, //写入代码     // 键值生成器
  }

填入:

if (this.courseData[this.currentDayIndex].courses.length > 0) {

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

  }, (course: CourseItem) => course.id)

思路:

  • if 条件:当前天有课程才显示列表
  • ForEach 第一个参数:当前天的课程数组
  • 键值生成器:用课程 id 做唯一标识

填空 11:空状态居中(第 377-379 行)

模板:

.layoutWeight(1)
//写入代码
        // 垂直居中
         // 水平居中

填入:

.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)

思路: 注释说"垂直居中"和"水平居中",对应 Flex 布局的两个属性。


填空 12:时间标签 + 课程信息(第 394-417 行)

时间标签 Column 内部:

Text(course.time.split('-')[0])
  .fontSize(14)
  .fontColor('#007DFF')
Text('|')
  .fontSize(12)
  .fontColor('#007DFF')
  .margin({ top: 2, bottom: 2 })
Text(course.time.split('-')[1])
  .fontSize(14)
  .fontColor('#007DFF')

课程信息 Column 内部:

Text(course.name)
  .fontSize(18)
  .fontColor('#333333')
  .fontWeight(FontWeight.Medium)
Text(`${course.classroom} | ${course.teacher}`)
  .fontSize(14)
  .fontColor('#666666')
  .margin({ top: 4 })

思路: course.time 格式是 "08:00-09:40",用 split('-') 拆成开始和结束时间。竖线 | 做分隔。课程信息用模板字符串拼接教室和教师。


填空 13:背景/圆角/阴影 + 手势(第 425-438 行)

Row 属性链:

.backgroundColor('#FFFFFF')
.borderRadius(12)
.shadow({ radius: 2, color: '#1A000000', offsetX: 0, offsetY: 1 })

手势参数:

PanGesture({
  direction: PanDirection.Left,
  distance: 50
})

onActionEnd 内部:

this.deletingCourse = course
this.showDeleteConfirm()

思路: 注释已经标注了"白色背景""圆角""阴影效果""左滑手势""滑动距离阈值"。左滑结束时记录要删除的课程,弹出确认框。


填空 14:showCourseDetail + deleteCourse + 数据模型(第 451-513 行)

showCourseDetail 补全:

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

deleteCourse 补全:

const currentDayCourses = this.courseData[this.currentDayIndex].courses
const index = currentDayCourses.findIndex(course => course.id === this.deletingCourse!.id)
if (index !== -1) {
  this.courseData[this.currentDayIndex].courses.splice(index, 1)
  this.courseData = JSON.parse(JSON.stringify(this.courseData))
}

CourseDay 类:

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

CourseItem 类:

class CourseItem {
  id: string = ''
  name: string = ''
  time: string = ''
  classroom: string = ''
  teacher: string = ''
}

思路: AlertDialog 的参数参考注释中的 emoji 提示。deleteCourse 用 findIndex 找到课程索引,splice 删除,JSON.parse(JSON.stringify()) 触发 UI 更新。


三、评分标准速查(100 分)

分类分值考点
项目结构和数据模型20 分状态变量声明 + 数据模型类定义
主界面布局35 分整体布局 + 星期导航 + 课程列表
课程布局20 分时间标签 + 课程信息 + 样式 + 滑动删除
交互功能15 分课程详情对话框 + 删除并更新 UI
界面美观度10 分颜色/字体/间距/阴影/交互反馈

四、练习建议

  1. 把模板的 //写入代码 全部删掉,变成空行
  2. 只看注释和已有代码,自己尝试填
  3. 填不出来的标记一下,看参考答案理解
  4. 合上答案,从头再填一遍
  5. 重复 2-3 遍,直到不看参考答案也能填完