随手记备忘录小应用 - HarmonyOS ArkUI 开发实战-PC版本

在这里插入图片描述

一、应用概述

随手记备忘录小应用是一款基于HarmonyOS ArkUI框架开发的轻量级待办事项管理工具。在快节奏的现代生活中,人们经常需要记录各种琐事、提醒事项和临时想法,传统的纸质备忘录容易丢失且不便管理,而手机自带的备忘录应用往往功能过于复杂。本应用旨在提供一个简洁、高效、易用的备忘录解决方案,让用户能够快速记录、查看和管理日常事务。

1.1 应用定位

随手记备忘录定位于"极简主义"工具应用,核心设计理念是"少即是多"。应用摒弃了繁杂的分类、标签、提醒等功能,专注于最核心的"记录"和"管理"两个操作。这种设计理念使得用户可以在几秒钟内完成一条备忘录的添加或删除,极大地提升了使用效率。

1.2 目标用户群体

  • 忙碌的上班族:需要快速记录会议时间、待办事项、临时任务
  • 学生群体:记录作业截止日期、考试安排、社团活动
  • 家庭主妇:记录购物清单、家务安排、家庭事务
  • 老年人群体:简单的操作界面,无需复杂学习成本

1.3 核心功能特性

功能模块功能描述技术实现
快速输入提供输入框供用户输入备忘内容TextInput组件
一键添加点击按钮即可添加新备忘录Button组件
列表展示以列表形式展示所有备忘录条目List + ForEach组件
单条删除每条备忘录可单独删除Button + filter方法
实时更新数据变化后界面自动刷新@State状态管理

1.4 应用界面预览

应用界面采用经典的垂直布局结构,从上到下依次为:

  • 顶部导航栏:包含返回按钮和应用标题,采用浅灰色背景
  • 输入区域:包含输入框和添加按钮,是用户的主要操作区
  • 列表区域:展示所有备忘录条目,支持滚动浏览

二、技术架构设计

2.1 整体架构图

┌─────────────────────────────────────────────────────────────┐
│                      MemoApp 组件                            │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────────────────────────────────────────┐   │
│  │              状态管理层 (@State)                      │   │
│  │  ┌─────────────────┐  ┌──────────────────────────┐  │   │
│  │  │   inputText_1   │  │       memos_1[]         │  │   │
│  │  │   (输入内容)     │  │    (备忘录数组)          │  │   │
│  │  └─────────────────┘  └──────────────────────────┘  │   │
│  └─────────────────────────────────────────────────────┘   │
│                            ↓                                │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              视图层 (build方法)                       │   │
│  │  ┌───────────────────────────────────────────────┐  │   │
│  │  │  Row (导航栏)                                  │  │   │
│  │  │  ├── Button (返回)                            │  │   │
│  │  │  └── Text (标题)                              │  │   │
│  │  └───────────────────────────────────────────────┘  │   │
│  │  ┌───────────────────────────────────────────────┐  │   │
│  │  │  Column (内容区)                               │  │   │
│  │  │  ├── TextInput (输入框)                        │  │   │
│  │  │  ├── Button (添加按钮)                         │  │   │
│  │  │  ├── Text (列表标题)                           │  │   │
│  │  │  └── List (备忘录列表)                         │  │   │
│  │  │      └── ForEach → ListItem → Row              │  │   │
│  │  └───────────────────────────────────────────────┘  │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

2.2 数据流设计

本应用采用单向数据流架构,数据从状态层流向视图层,用户操作触发状态更新,进而驱动视图刷新:

用户输入 → onChange回调 → 更新inputText_1状态
                                    ↓
点击添加按钮 → 验证输入 → 更新memos_1数组 → 触发UI刷新
                                    ↓
点击删除按钮 → filter过滤 → 更新memos_1数组 → 触发UI刷新

2.3 组件层级关系

Column (根容器)
├── Row (导航栏容器)
│   ├── Button (返回按钮)
│   └── Text (应用标题)
└── Column (内容容器)
    ├── TextInput (输入框组件)
    ├── Button (添加按钮组件)
    ├── Text (列表标题)
    └── List (列表容器)
        └── ForEach (循环渲染)
            └── ListItem (列表项容器)
                └── Row (列表项布局)
                    ├── Text (备忘内容)
                    └── Button (删除按钮)

2.4 技术选型说明

技术点选择方案选择理由
开发语言ArkTSHarmonyOS官方推荐,强类型支持,编译时检查
UI框架ArkUI声明式代码简洁,状态驱动,易于维护
状态管理@State装饰器轻量级,适合简单应用,自动触发UI刷新
列表渲染List + ForEach高性能,支持滚动,自动回收不可见项
路由导航router API官方推荐,支持页面跳转和返回

三、核心组件详解

3.1 TextInput组件深度解析

TextInput是用户输入的核心组件,在本应用中承担着接收用户备忘内容的重要职责。

3.1.1 基础属性配置
TextInput({ placeholder: '写下你想记的事情...' })
  .width('90%')           // 设置宽度为父容器的90%
  .height(48)             // 设置高度为48vp
  .margin({ top: 20 })    // 设置顶部外边距为20vp
  .onChange((value_1: string) => {
    this.inputText_1 = value_1;  // 实时更新状态变量
  })
3.1.2 TextInput属性详解表
属性名类型默认值说明
placeholderstring-输入框为空时显示的提示文本
widthLength-输入框宽度,支持数字、百分比、字符串
heightLength-输入框高度
marginMargin-外边距,可设置top/bottom/left/right
typeInputTypeNormal输入类型,如Normal/Password/Email等
maxLengthnumber-最大输入字符数限制
enterKeyTypeEnterKeyTypeDone回车键类型,如Done/Search/Go等
caretColorResourceColor-光标颜色
placeholderColorResourceColor-占位符文本颜色
placeholderFontFont-占位符文本字体样式
3.1.3 TextInput事件处理
TextInput({ placeholder: '请输入内容' })
  // 内容变化事件
  .onChange((value: string) => {
    console.log('输入内容变化:' + value);
  })
  // 提交事件(按下回车键)
  .onSubmit(() => {
    console.log('用户按下回车键');
  })
  // 编辑状态变化事件
  .onEditChanged((isEditing: boolean) => {
    console.log('编辑状态:' + isEditing);
  })
  // 触摸事件
  .onTouch((event: TouchEvent) => {
    if (event.type === TouchType.Press) {
      console.log('输入框被按下');
    }
  })
3.1.4 TextInput样式定制
TextInput({ placeholder: '写下你想记的事情...' })
  .width('90%')
  .height(48)
  .margin({ top: 20 })
  .backgroundColor('#F5F5F5')           // 背景色
  .borderRadius(8)                      // 圆角
  .border({ width: 1, color: '#E0E0E0' }) // 边框
  .padding({ left: 16, right: 16 })     // 内边距
  .fontColor('#333333')                 // 文字颜色
  .fontSize(16)                         // 字体大小
  .fontWeight(FontWeight.Normal)        // 字体粗细
  .onChange((value_1: string) => {
    this.inputText_1 = value_1;
  })

3.2 Button组件深度解析

Button组件是用户交互的核心入口,在本应用中用于添加备忘录和删除备忘录两个场景。

3.2.1 添加按钮实现
Button('添加')
  .width('90%')
  .height(40)
  .margin({ top: 12 })
  .backgroundColor('#0A59F7')  // HarmonyOS主题蓝色
  .fontColor('#FFFFFF')        // 白色文字
  .fontSize(16)
  .fontWeight(FontWeight.Medium)
  .borderRadius(8)
  .onClick(() => {
    // 验证输入不为空
    if (this.inputText_1 !== '') {
      // 使用concat创建新数组,触发状态更新
      this.memos_1 = this.memos_1.concat([this.inputText_1]);
      // 清空输入框
      this.inputText_1 = '';
    }
  })
3.2.2 Button属性详解表
属性名类型默认值说明
labelstring-按钮显示文本
widthLength-按钮宽度
heightLength-按钮高度
backgroundColorResourceColor-背景颜色
fontColorResourceColor-文字颜色
fontSizeLength-字体大小
fontWeightFontWeightNormal字体粗细
borderRadiusLength-圆角半径
typeButtonTypeCapsule按钮类型:Capsule/Circle/Normal
stateEffectbooleantrue是否开启按压效果
3.2.3 Button事件处理
Button('添加')
  // 点击事件
  .onClick(() => {
    console.log('按钮被点击');
  })
  // 触摸事件
  .onTouch((event: TouchEvent) => {
    if (event.type === TouchType.Press) {
      console.log('按钮被按下');
    } else if (event.type === TouchType.Up) {
      console.log('按钮被释放');
    }
  })
  // 挂载完成事件
  .onAppear(() => {
    console.log('按钮已挂载');
  })
  // 即将卸载事件
  .aboutToDisappear(() => {
    console.log('按钮即将卸载');
  })
3.2.4 删除按钮实现
Button('删除')
  .width(60)
  .height(32)
  .fontSize(12)
  .backgroundColor('#FF3B30')  // 红色,表示危险操作
  .fontColor('#FFFFFF')
  .borderRadius(4)
  .onClick(() => {
    // 使用filter过滤掉当前索引的元素
    this.memos_1 = this.memos_1.filter((_, i_1: number) => i_1 !== index_1);
  })

3.3 List组件深度解析

List组件是展示备忘录列表的核心容器,具有高性能的滚动和回收机制。

3.3.1 List基础用法
List() {
  ForEach(this.memos_1, (item_1: string, index_1: number) => {
    ListItem() {
      Row() {
        Text(item_1)
          .fontSize(14)
          .layoutWeight(1)
        Button('删除')
          .width(60)
          .height(32)
          .fontSize(12)
          .backgroundColor('#FF3B30')
          .onClick(() => {
            this.memos_1 = this.memos_1.filter((_, i_1: number) => i_1 !== index_1);
          })
      }
      .padding(12)
      .width('100%')
    }
  })
}
.width('90%')
.margin({ top: 8 })
3.3.2 List属性详解表
属性名类型默认值说明
widthLength-列表宽度
heightLength-列表高度
dividerDivider-列表项分割线样式
scrollBarBarStateOff滚动条状态:On/Off/Auto
edgeEffectEdgeEffectSpring边缘滑动效果:Spring/Fade/None
layoutDirectionAxisVertical滚动方向:Vertical/Horizontal
chainAnimationOptionsChainAnimationOptions-链式动画配置
3.3.3 List事件处理
List() {
  // ... 列表内容
}
// 滚动事件
.onScroll((scrollOffset: number, scrollState: ScrollState) => {
  console.log('滚动偏移量:' + scrollOffset);
})
// 滚动到边缘事件
.onScrollEdge((side: Edge) => {
  console.log('滚动到边缘:' + side);
})
// 滚动停止事件
.onScrollStop(() => {
  console.log('滚动停止');
})
// 列表项点击事件
.onItemClick((item: Object, index: number) => {
  console.log('点击了第' + index + '项');
})

3.4 ForEach组件深度解析

ForEach是ArkUI中用于循环渲染的核心组件,能够根据数组数据动态生成列表项。

3.4.1 ForEach基础语法
ForEach(
  this.memos_1,                          // 数据源数组
  (item_1: string, index_1: number) => { // item生成函数
    ListItem() {
      // 列表项内容
    }
  },
  (item_1: string, index_1: number) => { // key生成函数(可选)
    return index_1.toString();
  }
)
3.4.2 ForEach参数说明
参数类型必填说明
arrArray数据源数组
itemGenerator(item: any, index?: number) => void列表项生成函数
keyGenerator(item: any, index?: number) => string键值生成函数,用于优化渲染
3.4.3 ForEach性能优化
// 推荐做法:提供keyGenerator函数
ForEach(
  this.memos_1,
  (item_1: string, index_1: number) => {
    ListItem() {
      // ...
    }
  },
  (item_1: string, index_1: number) => {
    // 使用索引作为唯一标识
    return 'memo_' + index_1;
  }
)

// 不推荐做法:不提供keyGenerator
ForEach(this.memos_1, (item_1: string) => {
  ListItem() {
    // ...
  }
})

四、状态管理详解

4.1 @State装饰器原理

@State是ArkUI中最基础的状态管理装饰器,被装饰的变量称为状态变量。当状态变量的值发生变化时,ArkUI框架会自动检测变化并触发UI组件的重新渲染。

@State inputText_1: string = '';           // 输入框内容状态
@State memos_1: string[] = [                // 备忘录数组状态
  '记得买牛奶',
  '明天开会',
  '周末去公园',
  '给妈妈打电话'
];

4.2 状态变量的特点

特点说明示例
响应式变量变化自动触发UI更新this.inputText_1 = '新值'
类型安全必须指定明确的类型@State count: number = 0
初始化必须提供初始值@State name: string = ''
私有性只能在当前组件内访问不能被外部组件直接修改

4.3 状态更新机制

4.3.1 基本类型状态更新
// 字符串类型
this.inputText_1 = '新的备忘内容';  // 直接赋值触发更新

// 数字类型
@State count: number = 0;
this.count = this.count + 1;  // 直接赋值触发更新

// 布尔类型
@State isVisible: boolean = true;
this.isVisible = false;  // 直接赋值触发更新
4.3.2 数组类型状态更新
// 方式一:使用concat创建新数组(推荐)
this.memos_1 = this.memos_1.concat(['新备忘录']);

// 方式二:使用filter过滤创建新数组(推荐)
this.memos_1 = this.memos_1.filter((_, i) => i !== index);

// 方式三:使用展开运算符(推荐)
this.memos_1 = [...this.memos_1, '新备忘录'];

// 方式四:直接修改数组元素(不推荐,可能不触发更新)
this.memos_1.push('新备忘录');  // 可能不触发UI更新

4.4 状态更新流程图

用户操作
    ↓
触发事件处理函数
    ↓
修改@State变量
    ↓
ArkUI框架检测变化
    ↓
标记需要更新的组件
    ↓
重新执行build方法
    ↓
生成新的虚拟DOM树
    ↓
与旧虚拟DOM树对比
    ↓
计算最小更新差异
    ↓
应用到实际DOM
    ↓
UI完成更新

4.5 状态管理最佳实践

4.5.1 数组操作规范
// ✅ 正确做法:创建新数组
addMemo(content: string) {
  this.memos_1 = [...this.memos_1, content];
}

removeMemo(index: number) {
  this.memos_1 = this.memos_1.filter((_, i) => i !== index);
}

// ❌ 错误做法:直接修改原数组
addMemo(content: string) {
  this.memos_1.push(content);  // 可能不触发更新
}

removeMemo(index: number) {
  this.memos_1.splice(index, 1);  // 可能不触发更新
}
4.5.2 状态变量命名规范
// ✅ 推荐命名:使用下划线后缀避免关键字冲突
@State inputText_1: string = '';
@State memos_1: string[] = [];

// ❌ 不推荐命名:可能与系统关键字冲突
@State input: string = '';     // input可能是保留字
@State list: string[] = [];     // list可能是保留字

五、UI布局实现详解

5.1 整体布局结构

本应用采用Column作为根容器,内部嵌套Row和Column实现复杂的布局结构。

Column() {
  // 导航栏
  Row() {
    Button('返回')
      .onClick(() => router.back())
    Text('随手记备忘录小应用')
      .fontSize(20)
      .fontWeight(FontWeight.Bold)
      .layoutWeight(1)
      .textAlign(TextAlign.Center)
  }
  .width('100%')
  .padding(12)
  .backgroundColor('#F1F3F5')

  // 内容区域
  Column() {
    // 输入框
    TextInput({ placeholder: '写下你想记的事情...' })
      .width('90%')
      .height(48)
      .margin({ top: 20 })
      .onChange((value_1: string) => {
        this.inputText_1 = value_1;
      })

    // 添加按钮
    Button('添加')
      .width('90%')
      .height(40)
      .margin({ top: 12 })
      .backgroundColor('#0A59F7')
      .onClick(() => {
        if (this.inputText_1 !== '') {
          this.memos_1 = this.memos_1.concat([this.inputText_1]);
          this.inputText_1 = '';
        }
      })

    // 列表标题
    Text('备忘录列表')
      .fontSize(16)
      .fontWeight(FontWeight.Medium)
      .margin({ top: 24, left: 20 })
      .width('90%')

    // 备忘录列表
    List() {
      ForEach(this.memos_1, (item_1: string, index_1: number) => {
        ListItem() {
          Row() {
            Text(item_1)
              .fontSize(14)
              .layoutWeight(1)
            Button('删除')
              .width(60)
              .height(32)
              .fontSize(12)
              .backgroundColor('#FF3B30')
              .onClick(() => {
                this.memos_1 = this.memos_1.filter((_, i_1: number) => i_1 !== index_1);
              })
          }
          .padding(12)
          .width('100%')
        }
      })
    }
    .width('90%')
    .margin({ top: 8 })
  }
  .width('100%')
  .layoutWeight(1)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')

5.2 布局属性详解

5.2.1 尺寸属性
属性类型说明示例
widthLength组件宽度.width('90%').width(200)
heightLength组件高度.height(48)
sizeSizeOptions同时设置宽高.size({ width: 200, height: 100 })
5.2.2 间距属性
属性类型说明示例
marginMargin外边距.margin({ top: 20, left: 10 })
paddingPadding内边距.padding(12).padding({ left: 16, right: 16 })
5.2.3 权重属性
// layoutWeight属性用于分配剩余空间
Row() {
  Text('标题')
    .layoutWeight(1)  // 占据剩余所有空间
  Button('操作')
    .width(60)        // 固定宽度
}

// 在Column中使用layoutWeight
Column() {
  Text('头部')
    .height(50)
  List()
    .layoutWeight(1)  // 占据剩余高度
  Text('底部')
    .height(50)
}

5.3 布局容器对比

容器布局方向特点适用场景
Column垂直子组件从上到下排列页面主体、垂直列表
Row水平子组件从左到右排列导航栏、工具栏、列表项
Stack层叠子组件堆叠显示覆盖层、徽章、水印
Flex弹性支持换行、对齐方式复杂布局、响应式布局
List列表高性能滚动、自动回收长列表、数据展示

六、样式定制详解

6.1 颜色规范

本应用采用了HarmonyOS设计规范中的推荐颜色:

用途颜色值说明
主色调#0A59F7HarmonyOS主题蓝,用于主要操作按钮
危险操作#FF3B30红色,用于删除等危险操作
背景色#FFFFFF白色,主内容区背景
导航栏背景#F1F3F5浅灰色,区分导航区域
文字主色#333333深灰色,主要文字内容
文字辅色#666666中灰色,次要文字内容

6.2 字体规范

// 标题字体
Text('随手记备忘录小应用')
  .fontSize(20)                    // 标题字号
  .fontWeight(FontWeight.Bold)    // 粗体

// 副标题字体
Text('备忘录列表')
  .fontSize(16)                    // 副标题字号
  .fontWeight(FontWeight.Medium)  // 中等粗细

// 正文字体
Text(item_1)
  .fontSize(14)                    // 正文字号
  .fontWeight(FontWeight.Normal)  // 正常粗细

// 小字体
Button('删除')
  .fontSize(12)                    // 小字号

6.3 圆角规范

// 按钮圆角
Button('添加')
  .borderRadius(8)  // 中等圆角

// 输入框圆角
TextInput({ placeholder: '写下你想记的事情...' })
  .borderRadius(8)

// 列表项圆角
Row() {
  // ...
}
.borderRadius(4)  // 小圆角

6.4 间距规范

元素marginpadding说明
导航栏-12导航栏内边距
输入框top: 20-输入框顶部间距
添加按钮top: 12-按钮顶部间距
列表标题top: 24, left: 20-标题间距
列表项-12列表项内边距

七、完整代码示例

7.1 完整源代码

import { router } from '@kit.ArkUI';

@Entry
@Component
struct MemoApp {
  // 状态变量:存储输入框内容
  @State inputText_1: string = '';
  
  // 状态变量:存储备忘录列表数据
  @State memos_1: string[] = [
    '记得买牛奶',
    '明天开会',
    '周末去公园',
    '给妈妈打电话'
  ];

  build() {
    Column() {
      // 导航栏
      Row() {
        Button('返回')
          .onClick(() => router.back())
        Text('随手记备忘录小应用')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .layoutWeight(1)
          .textAlign(TextAlign.Center)
      }
      .width('100%')
      .padding(12)
      .backgroundColor('#F1F3F5')

      // 内容区域
      Column() {
        // 输入框
        TextInput({ placeholder: '写下你想记的事情...' })
          .width('90%')
          .height(48)
          .margin({ top: 20 })
          .onChange((value_1: string) => {
            this.inputText_1 = value_1;
          })

        // 添加按钮
        Button('添加')
          .width('90%')
          .height(40)
          .margin({ top: 12 })
          .backgroundColor('#0A59F7')
          .onClick(() => {
            if (this.inputText_1 !== '') {
              this.memos_1 = this.memos_1.concat([this.inputText_1]);
              this.inputText_1 = '';
            }
          })

        // 列表标题
        Text('备忘录列表')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
          .margin({ top: 24, left: 20 })
          .width('90%')

        // 备忘录列表
        List() {
          ForEach(this.memos_1, (item_1: string, index_1: number) => {
            ListItem() {
              Row() {
                Text(item_1)
                  .fontSize(14)
                  .layoutWeight(1)
                Button('删除')
                  .width(60)
                  .height(32)
                  .fontSize(12)
                  .backgroundColor('#FF3B30')
                  .onClick(() => {
                    this.memos_1 = this.memos_1.filter((_, i_1: number) => i_1 !== index_1);
                  })
              }
              .padding(12)
              .width('100%')
            }
          })
        }
        .width('90%')
        .margin({ top: 8 })
      }
      .width('100%')
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#FFFFFF')
  }
}

7.2 代码结构说明

代码区域行数功能说明
导入语句1导入router模块
组件声明3-5定义MemoApp组件
状态变量6-13定义输入内容和备忘录数组
导航栏16-25返回按钮和标题
输入框28-33备忘内容输入
添加按钮35-45添加备忘录功能
列表标题47-51备忘录列表标题
备忘录列表53-69展示和删除备忘录

八、组件对比分析

8.1 TextInput与其他输入组件对比

组件用途特点适用场景
TextInput单行文本输入简单易用,适合短文本用户名、搜索、备忘内容
TextArea多行文本输入支持换行,适合长文本评论、描述、文章内容
Search搜索输入自带搜索图标和清除按钮搜索功能
PasswordInput密码输入自动隐藏输入内容密码、敏感信息

8.2 Button与其他交互组件对比

组件用途特点适用场景
Button通用按钮样式丰富,事件简单提交、确认、导航
Toggle开关切换二态切换,状态明确设置开关、功能启用
Checkbox多选框支持多选,状态独立多选列表、选项组
Radio单选按钮互斥选择,状态关联单选列表、选项组
Slider滑动条连续值选择音量、亮度调节

8.3 List与其他容器组件对比

组件用途特点适用场景
List列表容器高性能滚动,自动回收长列表、数据展示
Column垂直容器简单垂直排列页面布局、固定内容
Grid网格容器规则网格排列图片墙、应用列表
Scroll滚动容器通用滚动容器长内容滚动
WaterFlow瀑布流不规则高度排列图片瀑布流

九、最佳实践

9.1 状态管理最佳实践

// ✅ 推荐:使用不可变数据更新
addMemo(content: string) {
  if (content.trim() !== '') {
    this.memos_1 = [...this.memos_1, content.trim()];
    this.inputText_1 = '';
  }
}

// ✅ 推荐:封装业务逻辑
removeMemo(index: number) {
  if (index >= 0 && index < this.memos_1.length) {
    this.memos_1 = this.memos_1.filter((_, i) => i !== index);
  }
}

// ✅ 推荐:数据验证
validateInput(text: string): boolean {
  return text !== null && text.trim() !== '' && text.length <= 100;
}

9.2 性能优化最佳实践

// ✅ 推荐:为ForEach提供key生成函数
ForEach(
  this.memos_1,
  (item_1: string, index_1: number) => {
    ListItem() {
      // ...
    }
  },
  (item_1: string, index_1: number) => {
    return 'memo_' + index_1 + '_' + item_1.length;
  }
)

// ✅ 推荐:使用LazyForEach处理大数据
LazyForEach(
  this.memoDataSource,
  (item: MemoItem) => {
    ListItem() {
      // ...
    }
  },
  (item: MemoItem) => item.id
)

9.3 用户体验最佳实践

// ✅ 推荐:输入验证和提示
Button('添加')
  .onClick(() => {
    if (this.inputText_1.trim() === '') {
      // 显示提示:请输入内容
      return;
    }
    if (this.inputText_1.length > 100) {
      // 显示提示:内容过长
      return;
    }
    this.memos_1 = [...this.memos_1, this.inputText_1.trim()];
    this.inputText_1 = '';
    // 显示提示:添加成功
  })

// ✅ 推荐:删除确认
Button('删除')
  .onClick(() => {
    AlertDialog.show({
      title: '确认删除',
      message: '确定要删除这条备忘录吗?',
      primaryButton: {
        value: '取消',
        action: () => {}
      },
      secondaryButton: {
        value: '删除',
        action: () => {
          this.memos_1 = this.memos_1.filter((_, i) => i !== index_1);
        }
      }
    });
  })

9.4 代码组织最佳实践

// ✅ 推荐:将样式提取为常量
const STYLES = {
  colors: {
    primary: '#0A59F7',
    danger: '#FF3B30',
    background: '#FFFFFF',
    navBackground: '#F1F3F5'
  },
  sizes: {
    titleSize: 20,
    subtitleSize: 16,
    bodySize: 14,
    smallSize: 12
  },
  spacing: {
    small: 8,
    medium: 12,
    large: 20,
    xlarge: 24
  }
};

// ✅ 推荐:将业务逻辑提取为方法
@Component
struct MemoApp {
  @State inputText_1: string = '';
  @State memos_1: string[] = [];

  // 添加备忘录
  addMemo() {
    if (this.validateInput(this.inputText_1)) {
      this.memos_1 = [...this.memos_1, this.inputText_1.trim()];
      this.inputText_1 = '';
    }
  }

  // 删除备忘录
  removeMemo(index: number) {
    this.memos_1 = this.memos_1.filter((_, i) => i !== index);
  }

  // 验证输入
  validateInput(text: string): boolean {
    return text !== null && text.trim() !== '' && text.length <= 100;
  }

  build() {
    // ...
  }
}

十、扩展功能设计

10.1 数据持久化

import preferences from '@ohos.data.preferences';

// 保存备忘录到本地存储
async saveMemos() {
  try {
    const context = getContext(this);
    const pref = await preferences.getPreferences(context, 'memo_store');
    await pref.put('memos', JSON.stringify(this.memos_1));
    await pref.flush();
  } catch (error) {
    console.error('保存失败:' + error);
  }
}

// 从本地存储加载备忘录
async loadMemos() {
  try {
    const context = getContext(this);
    const pref = await preferences.getPreferences(context, 'memo_store');
    const data = await pref.get('memos', '[]');
    this.memos_1 = JSON.parse(data as string);
  } catch (error) {
    console.error('加载失败:' + error);
  }
}

10.2 分类管理功能

// 定义备忘录数据模型
class MemoItem {
  id: string = '';
  content: string = '';
  category: string = 'default';
  createTime: number = 0;
  isCompleted: boolean = false;
}

// 分类数据
@State categories: string[] = ['工作', '生活', '学习', '其他'];
@State currentCategory: string = 'all';

// 按分类过滤
get filteredMemos(): MemoItem[] {
  if (this.currentCategory === 'all') {
    return this.memos_1;
  }
  return this.memos_1.filter(item => item.category === this.currentCategory);
}

10.3 搜索功能

@State searchText: string = '';

// 搜索框
TextInput({ placeholder: '搜索备忘录...' })
  .width('90%')
  .height(40)
  .margin({ top: 10 })
  .onChange((value: string) => {
    this.searchText = value;
  })

// 搜索过滤
get searchedMemos(): string[] {
  if (this.searchText === '') {
    return this.memos_1;
  }
  return this.memos_1.filter(item => 
    item.toLowerCase().includes(this.searchText.toLowerCase())
  );
}

10.4 优先级功能

// 定义优先级
enum Priority {
  LOW = 'low',
  MEDIUM = 'medium',
  HIGH = 'high'
}

// 带优先级的备忘录模型
class PriorityMemo {
  id: string = '';
  content: string = '';
  priority: Priority = Priority.MEDIUM;
  createTime: number = 0;
}

// 优先级颜色映射
getPriorityColor(priority: Priority): string {
  const colors = {
    [Priority.LOW]: '#4CAF50',      // 绿色
    [Priority.MEDIUM]: '#FF9800',   // 橙色
    [Priority.HIGH]: '#F44336'      // 红色
  };
  return colors[priority];
}

10.5 完成状态功能

// 带完成状态的备忘录模型
class TodoItem {
  id: string = '';
  content: string = '';
  isCompleted: boolean = false;
  createTime: number = 0;
}

// 切换完成状态
toggleComplete(id: string) {
  this.memos_1 = this.memos_1.map(item => {
    if (item.id === id) {
      return { ...item, isCompleted: !item.isCompleted };
    }
    return item;
  });
}

// 显示样式
Text(item.content)
  .fontColor(item.isCompleted ? '#999999' : '#333333')
  .decoration({ type: item.isCompleted ? TextDecorationType.LineThrough : TextDecorationType.None })

十一、性能优化策略

11.1 列表渲染优化

// 使用LazyForEach替代ForEach处理大量数据
class MemoDataSource implements IDataSource {
  private memos: string[] = [];
  private listeners: DataChangeListener[] = [];

  totalCount(): number {
    return this.memos.length;
  }

  getData(index: number): string {
    return this.memos[index];
  }

  registerDataChangeListener(listener: DataChangeListener): void {
    this.listeners.push(listener);
  }

  unregisterDataChangeListener(listener: DataChangeListener): void {
    this.listeners = this.listeners.filter(l => l !== listener);
  }
}

// 在List中使用LazyForEach
List() {
  LazyForEach(
    this.memoDataSource,
    (item: string, index: number) => {
      ListItem() {
        // 列表项内容
      }
    },
    (item: string, index: number) => {
      return 'memo_' + index;
    }
  )
}

11.2 状态更新优化

// ✅ 批量更新
addMultipleMemos(contents: string[]) {
  const newMemos = contents.filter(c => c.trim() !== '');
  this.memos_1 = [...this.memos_1, ...newMemos];
}

// ❌ 逐个更新(性能差)
addMultipleMemosSlow(contents: string[]) {
  contents.forEach(c => {
    if (c.trim() !== '') {
      this.memos_1 = [...this.memos_1, c];  // 每次都触发更新
    }
  });
}

11.3 组件复用优化

// 提取列表项为独立组件
@Component
struct MemoItem {
  @Prop content: string = '';
  @Prop index: number = 0;
  onDelete: (index: number) => void = () => {};

  build() {
    Row() {
      Text(this.content)
        .fontSize(14)
        .layoutWeight(1)
      Button('删除')
        .width(60)
        .height(32)
        .fontSize(12)
        .backgroundColor('#FF3B30')
        .onClick(() => {
          this.onDelete(this.index);
        })
    }
    .padding(12)
    .width('100%')
  }
}

// 在主组件中使用
List() {
  ForEach(this.memos_1, (item: string, index: number) => {
    ListItem() {
      MemoItem({
        content: item,
        index: index,
        onDelete: (i: number) => {
          this.memos_1 = this.memos_1.filter((_, idx) => idx !== i);
        }
      })
    }
  })
}

十二、总结

随手记备忘录小应用是一个典型的HarmonyOS ArkUI入门项目,通过这个项目我们学习了以下核心知识点:

12.1 技术要点总结

技术点学习内容实践应用
状态管理@State装饰器的使用管理输入内容和备忘录列表
组件使用TextInput、Button、List、ForEach构建完整的用户界面
布局技术Column、Row、layoutWeight实现响应式布局
事件处理onChange、onClick处理用户交互
数组操作concat、filter实现添加和删除功能

12.2 开发流程总结

需求分析 → 界面设计 → 组件选择 → 状态设计 → 事件处理 → 样式定制 → 测试优化

12.3 最佳实践总结

  1. 状态管理:使用不可变数据更新数组,确保UI正确刷新
  2. 性能优化:为ForEach提供key生成函数,大数据使用LazyForEach
  3. 代码组织:提取样式常量,封装业务逻辑方法
  4. 用户体验:添加输入验证、删除确认等交互优化

12.4 扩展方向

  • 数据持久化:使用Preferences存储备忘录数据
  • 分类管理:支持按类别分组备忘录
  • 搜索功能:支持关键字搜索备忘录
  • 优先级设置:支持标记重要程度
  • 完成状态:支持标记已完成事项
  • 提醒功能:支持定时提醒通知

通过这个项目的学习,开发者可以掌握HarmonyOS ArkUI的基础开发技能,为开发更复杂的应用打下坚实基础。本应用虽然功能简单,但涵盖了状态管理、列表渲染、事件处理、样式定制等核心知识点,是学习ArkUI开发的优秀实践案例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值