# 鸿蒙ArkTS编程规则与最佳实践 ## 语法差异规则:ArkTS vs TypeScript ### 1. 空值检查规则 ```typescript // ❌ 错误: 未对可能为null的对象执行检查 this.dbObject.executeSql(sql); // ✅ 正确: 执行null检查 if (this.dbObject) { this.dbObject.executeSql(sql); } ``` ### 2. 解构赋值规则(已支持) ```typescript // ✅ 正确: ArkTS 4.0+ 已支持解构赋值语法 for (const [key, value] of Object.entries(obj)) { // 处理逻辑 } // ✅ 正确: 数组解构赋值 const [first, second, ...rest] = array; // ✅ 正确: 对象解构赋值 const { name, age, ...otherProps } = person; ``` ### 3. 异步API调用规则 ```typescript // ❌ 错误: 回调参数类型不匹配 dbStore.executeSql(sql, (err, result: ResultSet) => { // 处理逻辑 }); // ✅ 正确: 使用Promise模式 dbStore.executeSql(sql) .then(() => { // 成功处理 }) .catch((err: Error) => { // 错误处理 console.log(err.message); }); // ✅ 正确: 使用async/await模式 async function executeQuery() { try { await dbStore.executeSql(sql); // 成功处理 } catch (err: Error) { // 错误处理 console.log(err.message); } } ``` ### 4. 计算属性名规则(已支持) ```typescript // ✅ 正确: ArkTS 4.0+ 已支持计算属性名语法 const obj = { [CONSTANT.KEY]: value }; // ✅ 正确: 动态属性名 const propertyName = 'dynamicKey'; const obj = { [propertyName]: value }; ``` ### 5. 数据类型规则 ```typescript // ❌ 错误: 使用any或未指定泛型类型 const items = new Set(); const map = new Map(); // ✅ 正确: 明确指定泛型类型 const items = new Set(); const map = new Map(); // ✅ 正确: 使用类型推断 const items = new Set(); const map = new Map(); ``` ### 6. 错误对象类型规则 ```typescript // ❌ 错误: 使用隐式any类型的错误对象 try { // 代码 } catch (e) { console.log(`错误: ${e}`); } // ✅ 正确: 明确指定错误对象的类型 try { // 代码 } catch (e: Error) { console.log(`错误: ${e.message}`); } // ✅ 正确: 使用unknown类型(更安全) try { // 代码 } catch (e: unknown) { if (e instanceof Error) { console.log(`错误: ${e.message}`); } else { console.log(`未知错误: ${e}`); } } ``` ### 7. 新的语法特性支持 #### 7.1 可选链操作符 ```typescript // ✅ 正确: 使用可选链操作符 const name = user?.profile?.name; const result = obj?.method?.(); ``` #### 7.2 空值合并操作符 ```typescript // ✅ 正确: 使用空值合并操作符 const value = input ?? defaultValue; const name = user?.name ?? 'Unknown'; ``` #### 7.3 模板字面量 ```typescript // ✅ 正确: 使用模板字面量 const message = `Hello, ${name}!`; const sql = `SELECT * FROM ${tableName} WHERE id = ${id}`; ``` ## 数据库操作最佳实践 ### 1. 表结构升级 ```typescript // ❌ 错误: 依赖回调处理的表结构升级 this.rdbStore.executeSql(tableInfoQuery, (err, result) => { // 处理逻辑 }); // ✅ 正确: 使用Promise模式并独立处理每个列的添加操作 this.rdbStore.executeSql(tableInfoQuery) .then(() => { // 为每个需要添加的列单独执行ALTER TABLE Object.keys(columnsToAdd).forEach(column => { const type = columnsToAdd[column]; this.rdbStore.executeSql(`ALTER TABLE ${tableName} ADD COLUMN ${column} ${type}`) .then(() => { /* 成功处理 */ }) .catch((err: Error) => { /* 错误处理 */ }); }); }); // ✅ 正确: 使用async/await模式 async function upgradeTable() { try { await this.rdbStore.executeSql(tableInfoQuery); for (const [column, type] of Object.entries(columnsToAdd)) { await this.rdbStore.executeSql(`ALTER TABLE ${tableName} ADD COLUMN ${column} ${type}`); } } catch (err: Error) { console.error('表结构升级失败:', err.message); } } ``` ### 2. 资源释放 ```typescript // ❌ 错误: 未关闭ResultSet this.rdbStore.query(predicates, (resultSet) => { // 处理逻辑 }); // ✅ 正确: 确保关闭ResultSet this.rdbStore.query(predicates, (resultSet) => { try { // 处理逻辑 } finally { resultSet.close(); } }); // ✅ 正确: 使用async/await模式 async function queryData() { const resultSet = await this.rdbStore.query(predicates); try { // 处理逻辑 } finally { resultSet.close(); } } ``` ## 对象字面量规则 ### 1. 复杂对象初始化(已支持) ```typescript // ✅ 正确: ArkTS 4.0+ 已支持复杂对象字面量初始化 const config = { complex: { nested: { value: someValue } } }; // ✅ 正确: 使用展开操作符 const baseConfig = { timeout: 5000 }; const extendedConfig = { ...baseConfig, retries: 3 }; ``` ### 2. 方法简写 ```typescript // ✅ 正确: 使用方法简写语法 const obj = { name: 'test', sayHello() { return `Hello, ${this.name}!`; } }; ``` ## 组件开发最佳实践 ### 1. 状态管理 ```typescript // ✅ 正确: 使用@State装饰器 @State count: number = 0; // ✅ 正确: 使用@Prop装饰器 @Prop title: string = ''; // ✅ 正确: 使用@Link装饰器 @Link isVisible: boolean = false; ``` ### 2. 生命周期方法 ```typescript // ✅ 正确: 使用async生命周期方法 async aboutToAppear() { await this.initializeData(); } // ✅ 正确: 使用Promise处理异步操作 aboutToAppear() { this.initializeData().then(() => { console.log('初始化完成'); }).catch((err: Error) => { console.error('初始化失败:', err.message); }); } ``` ### 3. 事件处理 ```typescript // ✅ 正确: 使用async事件处理 .onClick(async () => { try { await this.handleClick(); } catch (err: Error) { console.error('点击处理失败:', err.message); } }) // ✅ 正确: 使用箭头函数 .onClick((event: ClickEvent) => { this.handleClick(event); }) ``` ## 性能优化最佳实践 ### 1. 避免在build方法中进行复杂计算 ```typescript // ❌ 错误: 在build方法中进行复杂计算 build() { const expensiveResult = this.computeExpensiveValue(); return Column() { Text(expensiveResult) } } // ✅ 正确: 预先计算或使用缓存 @State private cachedResult: string = ''; aboutToAppear() { this.cachedResult = this.computeExpensiveValue(); } build() { return Column() { Text(this.cachedResult) } } ``` ### 2. 使用LazyForEach优化列表性能 ```typescript // ✅ 正确: 使用LazyForEach LazyForEach(this.dataSource, (item: DataItem) => { ListItem() { Text(item.name) } }, (item: DataItem) => item.id.toString()) ``` ## 命名规范 - 类名: PascalCase (例如 MediaTable) - 方法名: camelCase (例如 queryByParentPath) - 常量: UPPER_SNAKE_CASE (例如 DB_COLUMNS.FILE_PATH) - 私有属性: _camelCase (例如 _dbStore) - 组件名: PascalCase (例如 NewIndex) - 装饰器: @开头 (例如 @State, @Prop) ## 错误处理最佳实践 ### 1. 统一错误处理 ```typescript // ✅ 正确: 创建统一的错误处理函数 private handleError(error: unknown, context: string): void { if (error instanceof Error) { console.error(`${context} 失败:`, error.message); } else { console.error(`${context} 失败:`, String(error)); } } // 使用示例 try { await this.performOperation(); } catch (error: unknown) { this.handleError(error, '操作执行'); } ``` ### 2. 业务错误处理 ```typescript // ✅ 正确: 处理业务错误 try { await this.apiCall(); } catch (error: unknown) { if (error instanceof BusinessError) { console.error(`业务错误: ${error.code}, ${error.message}`); } else { console.error('未知错误:', error); } } ``` ## 类型安全最佳实践 ### 1. 使用类型断言 ```typescript // ✅ 正确: 安全的类型断言 const result = data as VideoItem; // ✅ 正确: 使用类型守卫 if (typeof data === 'object' && data !== null && 'name' in data) { const videoItem = data as VideoItem; } ``` ### 2. 接口定义 ```typescript // ✅ 正确: 定义清晰的接口 interface VideoItem { id: string; name: string; artist?: string; album?: string; duration: number; filePath: string; } ``` ## 调试和日志最佳实践 ### 1. 使用hilog进行日志记录 ```typescript // ✅ 正确: 使用hilog import hilog from '@ohos.hilog'; hilog.info(0x0000, 'TAG', '%{public}s', '信息日志'); hilog.warn(0x0000, 'TAG', '%{public}s', '警告日志'); hilog.error(0x0000, 'TAG', '%{public}s', '错误日志'); ``` ### 2. 条件日志 ```typescript // ✅ 正确: 使用条件日志避免性能影响 if (__DEV__) { console.log('调试信息:', data); } ``` - 私有属性: _camelCase (例如 _dbStore)