|
|
@@ -1,8 +1,3 @@
|
|
|
----
|
|
|
-description:
|
|
|
-globs:
|
|
|
-alwaysApply: true
|
|
|
----
|
|
|
# 鸿蒙ArkTS编程规则与最佳实践
|
|
|
|
|
|
## 语法差异规则:ArkTS vs TypeScript
|
|
|
@@ -18,20 +13,18 @@ if (this.dbObject) {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-### 2. 解构赋值规则
|
|
|
+### 2. 解构赋值规则(已支持)
|
|
|
```typescript
|
|
|
-// ❌ 错误: ArkTS不支持解构赋值语法
|
|
|
+// ✅ 正确: ArkTS 4.0+ 已支持解构赋值语法
|
|
|
for (const [key, value] of Object.entries(obj)) {
|
|
|
// 处理逻辑
|
|
|
}
|
|
|
|
|
|
-// ✅ 正确: 使用传统循环方式
|
|
|
-const keys = Object.keys(obj);
|
|
|
-for (let i = 0; i < keys.length; i++) {
|
|
|
- const key = keys[i];
|
|
|
- const value = obj[key];
|
|
|
- // 处理逻辑
|
|
|
-}
|
|
|
+// ✅ 正确: 数组解构赋值
|
|
|
+const [first, second, ...rest] = array;
|
|
|
+
|
|
|
+// ✅ 正确: 对象解构赋值
|
|
|
+const { name, age, ...otherProps } = person;
|
|
|
```
|
|
|
|
|
|
### 3. 异步API调用规则
|
|
|
@@ -50,16 +43,27 @@ dbStore.executeSql(sql)
|
|
|
// 错误处理
|
|
|
console.log(err.message);
|
|
|
});
|
|
|
+
|
|
|
+// ✅ 正确: 使用async/await模式
|
|
|
+async function executeQuery() {
|
|
|
+ try {
|
|
|
+ await dbStore.executeSql(sql);
|
|
|
+ // 成功处理
|
|
|
+ } catch (err: Error) {
|
|
|
+ // 错误处理
|
|
|
+ console.log(err.message);
|
|
|
+ }
|
|
|
+}
|
|
|
```
|
|
|
|
|
|
-### 4. 计算属性名规则
|
|
|
+### 4. 计算属性名规则(已支持)
|
|
|
```typescript
|
|
|
-// ❌ 错误: 不支持计算属性名语法
|
|
|
+// ✅ 正确: ArkTS 4.0+ 已支持计算属性名语法
|
|
|
const obj = { [CONSTANT.KEY]: value };
|
|
|
|
|
|
-// ✅ 正确: 使用对象属性赋值语法
|
|
|
-const obj = {};
|
|
|
-obj[CONSTANT.KEY] = value;
|
|
|
+// ✅ 正确: 动态属性名
|
|
|
+const propertyName = 'dynamicKey';
|
|
|
+const obj = { [propertyName]: value };
|
|
|
```
|
|
|
|
|
|
### 5. 数据类型规则
|
|
|
@@ -71,6 +75,10 @@ const map = new Map();
|
|
|
// ✅ 正确: 明确指定泛型类型
|
|
|
const items = new Set<string>();
|
|
|
const map = new Map<string, number>();
|
|
|
+
|
|
|
+// ✅ 正确: 使用类型推断
|
|
|
+const items = new Set<string>();
|
|
|
+const map = new Map<string, number>();
|
|
|
```
|
|
|
|
|
|
### 6. 错误对象类型规则
|
|
|
@@ -88,6 +96,40 @@ 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}`;
|
|
|
```
|
|
|
|
|
|
## 数据库操作最佳实践
|
|
|
@@ -110,6 +152,18 @@ this.rdbStore.executeSql(tableInfoQuery)
|
|
|
.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. 资源释放
|
|
|
@@ -127,13 +181,23 @@ this.rdbStore.query(predicates, (resultSet) => {
|
|
|
resultSet.close();
|
|
|
}
|
|
|
});
|
|
|
+
|
|
|
+// ✅ 正确: 使用async/await模式
|
|
|
+async function queryData() {
|
|
|
+ const resultSet = await this.rdbStore.query(predicates);
|
|
|
+ try {
|
|
|
+ // 处理逻辑
|
|
|
+ } finally {
|
|
|
+ resultSet.close();
|
|
|
+ }
|
|
|
+}
|
|
|
```
|
|
|
|
|
|
## 对象字面量规则
|
|
|
|
|
|
-### 1. 复杂对象初始化
|
|
|
+### 1. 复杂对象初始化(已支持)
|
|
|
```typescript
|
|
|
-// ❌ 错误: 不支持复杂对象字面量初始化
|
|
|
+// ✅ 正确: ArkTS 4.0+ 已支持复杂对象字面量初始化
|
|
|
const config = {
|
|
|
complex: {
|
|
|
nested: {
|
|
|
@@ -142,11 +206,104 @@ const config = {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-// ✅ 正确: 分步创建复杂对象
|
|
|
-const config = {};
|
|
|
-config.complex = {};
|
|
|
-config.complex.nested = {};
|
|
|
-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())
|
|
|
```
|
|
|
|
|
|
## 命名规范
|
|
|
@@ -155,4 +312,88 @@ config.complex.nested.value = someValue;
|
|
|
- 方法名: 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)
|
|
|
|