鸿蒙开发笔记1
经验1-反单引号

经验2-字符串资源
在鸿蒙(HarmonyOS)应用开发中,直接硬编码字符串(如直接在代码中写“首页”)虽然简单,但会导致严重问题。以下是详细分析,结合开发规范和实际场景,解释为何应通过资源文件加载字符串,而非直接硬编码:
1. 硬编码的核心问题
- 本地化困难:直接硬编码字符串(如
"首页")会使应用无法支持多语言。当需要翻译成其他语言(如英语"Home"或日语"ホーム")时,必须手动修改代码中的每个字符串,增加维护成本且易出错。 - 拼接错误风险:如果字符串由多个片段拼接(如
"欢迎来到" + "首页"),翻译时可能破坏句子完整性。例如,英语语序可能需调整为"Home Page",但硬编码拼接会导致大小写或语义混乱(如搜索结果1中的案例:"Rain tomorrow"和"Bring an umbrella"拼接后出现语法错误)。 - 违反开发规范:鸿蒙开发强调可维护性和国际化,硬编码不符合资源与代码分离的最佳实践(参考搜索结果1),可能导致应用审核失败或性能问题。
2. 通过资源加载的优势
- 统一管理:将字符串提取到资源文件(如
string.json),开发者只需维护一个文件,无需修改代码即可支持多语言。例如:- 在资源文件中定义:
{ "name": "home_page", "value": "首页" }
- 在资源文件中定义:
- 动态更新:资源文件支持运行时加载,便于动态切换语言或主题。例如,使用
@kit.I18n模块加载字符串:import { I18n } from '@kit.I18n'; let homeText = I18n.getI18nInstance().getString($r('app.string.home_page')); - 避免占位符问题:对于含变量的字符串(如“打开{appName}”),资源文件支持占位符(如
%s),确保翻译完整性:// string.json { "name": "open_app", "value": "打开%s" // 占位符设计,避免拼接错误 }
3. 实际开发建议
- 替代硬编码的方案:
- 使用HarmonyOS的资源管理机制(如
$r('app.string.xxx')加载字符串资源)。 - 在UI组件中直接引用资源ID,例如:
Text($r('app.string.home_page')) // 正确方式:加载资源而非硬编码
- 使用HarmonyOS的资源管理机制(如
- 注意事项:
- 所有界面文字(包括图片文字、音频字幕)都应避免硬编码(参考搜索结果1的约束)。
- 在涉及动态内容(如用户输入或网络数据)时,优先使用资源占位符而非字符串拼接。
总结
直接硬编码字符串(如“首页”)虽然编码快捷,但会破坏应用的可维护性、国际化支持,并增加错误风险。相反,通过资源文件加载字符串,能提升开发效率、确保多语言兼容性,并符合鸿蒙开发规范。推荐在项目中统一使用资源管理机制,以构建更健壮的HarmonyOS应用。

经验3
entry/src/main/ets/common、entryability、entrybackupability、utils、view、view model解释这几个文件
以下为鸿蒙应用开发的完整模块化设计指南,整合了各模块的核心功能、具体用法和交互关系:
📁 1. common(公共模块)
功能:全局资源管理与样式复用
具体用法:
// 常量定义(ColorConstants.ets)
export const PrimaryColor = '#007AFF'; // 全局主色
export const DangerColor = '#FF3B30'; // 警示色
// 样式工具(StyleUtils.ets)
export function textStyle(size: number, weight: number) {
return { fontSize: size, fontWeight: weight }; // 返回文本样式对象
}
使用场景:
import { PrimaryColor, textStyle } from '../common/StyleUtils';
Text('Hello World')
.fontColor(PrimaryColor) // 使用全局颜色
.style(textStyle(16, 500)) // 应用复用样式
⚙️ 2. entryability(主入口能力)
功能:应用启动与上下文管理
具体用法:
// 设置启动页
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Index', (err) => {
if (err) console.error('加载页面失败');
});
}
// 获取上下文
onCreate(want: Want): void {
const context = this.context;
AppStorage.setOrCreate('abilityContext', context); // 存储至全局
}
关键能力:
startAbility()启动其他AbilityterminateSelf()结束当前Ability
🔄 3. entrybackupability(备份能力)
功能:数据云备份与恢复
具体用法:
// 实现备份回调
onBackup(): void {
const data = AppStorage.get('userData'); // 获取待备份数据
// 序列化到云存储
}
onRestore(backupData: any): void {
AppStorage.setOrCreate('userData', backupData); // 恢复数据
}
触发场景:设备迁移时自动执行云备份/恢复
🧰 4. utils(工具模块)
功能:封装通用工具函数
具体用法:
// 文件操作(FileUtils.ets)
import fs from '@kit.FileManagementKit';
export function readFile(path: string): string {
return fs.readTextSync(path); // 同步读取文本
}
// 数据处理(DateUtils.ets)
export function formatDate(date: Date): string {
return `${date.getFullYear()}-${date.getMonth()+1}`; // 简化日期格式
}
调用示例:
import { formatDate } from '../utils/DateUtils';
Text(formatDate(new Date())) // 显示"2026-1"
🖼️ 5. view(视图层)
功能:UI构建与组件封装
具体用法:
// 页面组件(Index.ets)
@Entry
@Component
struct Index {
@State count: number = 0; // 响应式状态
build() {
Column() {
Button('点击+1').onClick(() => { this.count++ })
Text(`计数: ${this.count}`) // 自动更新
}
}
}
// 自定义组件(CustomButton.ets)
@Component
export struct CustomButton {
label: string = '按钮';
onClick: () => void;
build() {
Button(this.label).onClick(() => this.onClick())
}
}
🧠 6. viewmodel(视图模型层)
功能:状态管理与业务逻辑
具体用法:
// 状态管理(ClockViewModel.ets)
export class ClockViewModel {
@State time: string = '';
startTimer() {
setInterval(() => {
this.time = new Date().toLocaleTimeString(); // 每秒更新
}, 1000);
}
}
// 业务逻辑(BookUtils.ets)
import { DocumentViewPicker } from '@kit.FilePickerKit';
export function importBook() {
const picker = new DocumentViewPicker();
picker.select().then(file => { // 文件选择
// 处理导入逻辑
});
}
与View交互:
const vm = new ClockViewModel();
vm.startTimer(); // 启动定时器
Text(vm.time) // 绑定动态时间
🔗 模块调用关系
设计原则
- MVVM数据流:View层通过
@State监听ViewModel变化,实现UI自动更新- 模块隔离:业务逻辑(ViewModel)、工具(Utils)、UI(View)分层解耦
- 全局通信:使用
AppStorage共享上下文,避免跨模块直接依赖- 备份机制:通过entrybackupability实现无感数据迁移,提升用户体验
此设计符合鸿蒙官方推荐架构,已在18大行业应用验证(参考《鸿蒙应用开发常见问题手册》),可有效解决页面跳转错误、数据同步失效等高频问题。
经验4
aboutToAppear() 生命周期详解
在鸿蒙(HarmonyOS)的 ArkUI 声明式开发范式中,aboutToAppear() 是自定义组件的核心生命周期函数之一。它用于在组件初始化阶段执行关键操作,例如数据加载或状态设置。以下是对其详细解释,基于鸿蒙官方规范和最佳实践:
1. 触发时机与定义
aboutToAppear()在自定义组件(通过@Component装饰)的新实例创建后立即执行,发生在build()函数之前 123。- 此时组件尚未渲染到界面,但已初始化成员变量(例如通过本地默认值或构造函数参数)。
- 示例流程:当组件首次加载或重建时,执行顺序为:
- 成员变量初始化 →
aboutToAppear()→build()→ 子组件渲染。
- 成员变量初始化 →
2. 主要功能与用途
- 初始化数据:适合执行数据获取逻辑,如从网络、本地存储加载数据。
- 修改状态变量:允许在函数内更改
@State、@Prop等状态变量,这些变更会在后续build()中生效,驱动 UI 更新。 - 资源注册:可绑定事件监听器或订阅外部服务(如媒体查询),但需在
aboutToDisappear()中清理以避免内存泄漏。
例如,在媒体查询场景中绑定回调:
aboutToAppear() {
this.listener.on('change', (mediaQueryResult) => {
// 处理横竖屏切换逻辑
});
}
aboutToDisappear() {
this.listener.off('change'); // 清理注册
}
3. 与相关生命周期的区别
- vs
onPageShow():aboutToAppear()适用于所有@Component组件(包括子组件),而onPageShow()仅限@Entry装饰的页面级组件12。- 页面首次加载时,执行顺序为:
aboutToAppear()→build()→onPageShow();页面返回时,仅触发onPageShow(),而aboutToAppear()不会重复执行。
- vs
aboutToDisappear():aboutToDisappear()在组件销毁前调用,用于清理资源(如定时器、订阅),两者需成对使用以确保资源安全释放。
4. 最佳实践与注意事项
- 异步操作:若涉及耗时任务(如网络请求),必须使用异步方式(
async/await或Promise),避免阻塞build()渲染,影响页面冷启动性能。例如:async aboutToAppear() { const data = await this.loadData(); // 异步加载数据 this.dataList = data; // 更新状态变量 } - 避免滥用:
- 不适用于频繁触发的逻辑(如 UI 交互),仅作一次性初始化。
- 在
aboutToAppear()中修改@Link变量需谨慎,可能引发状态同步问题。
- 性能优化:组件通过条件渲染(如
if分支)删除时,会触发aboutToDisappear(),但未渲染的组件可能强制触发aboutToAppear()以保证生命周期完整性(API12+ 规格)。
总结
aboutToAppear() 是组件生命周期的“入口点”,专注于初始化阶段的数据准备和状态设置。合理使用它能提升组件加载效率,但需结合异步处理和资源清理(在 aboutToDisappear() 中)以确保应用稳定性。如需页面级显示/隐藏逻辑,应优先使用 onPageShow() 和 onPageHide()。
经验5
在文件系统中,"../../" 是一个相对路径的表示方式,其含义如下:
路径解析说明
-
.和..的含义.(单点):表示当前目录(如./file.txt表示当前目录下的file.txt)。..(双点):表示上一级目录(如../file.txt表示父目录下的file.txt)。
-
../../的具体含义
该路径表示:- 先返回当前目录的父目录(一级向上);
- 再返回父目录的父目录(二级向上),即上两级目录。
示例:
若当前路径为/a/b/c/,则../../对应/a/目录。
在鸿蒙(HarmonyOS)中的注意事项
- 应用沙箱路径:
在鸿蒙开发中,应用的文件操作通常基于沙箱路径(如context.cacheDir获取缓存路径)。使用../../需注意当前工作目录的基准位置,避免越权访问沙箱外的文件。 - 路径协议规范:
鸿蒙支持多种路径协议(如fd://标识媒体句柄、internal://表示私有目录)。直接使用../../属于相对路径操作,需确保目标路径在应用沙箱内合法。
使用场景示例
假设需要读取上两级目录的配置文件:
// 伪代码示例:基于当前目录向上回溯两级
import fs from '@kit.FileKit';
// 获取当前工作目录(假设为 /app/com.example/foo/bar/)
const currentDir = ...;
const targetDir = currentDir + '../../'; // 目标路径:/app/com.example/foo/
const configFile = targetDir + 'config.json';
// 读取文件
fs.readTextSync(configFile);
⚠️ 安全提示:
在鸿蒙中频繁使用../../可能引发路径越界风险,建议优先使用绝对路径(如context.filesDir)或内部协议路径(如internal://cache)。
更多推荐




所有评论(0)