| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- ---
- description:
- globs:
- alwaysApply: false
- ---
- # 鸿蒙ArkTS编程规则与最佳实践
- ## 语法差异规则:ArkTS vs TypeScript
- 在需要更新经验规则记忆的时候,请及时更新.cursor\rules\cursorrules.mdc文件
- ### 1. 空值检查规则
- ```typescript
- // ❌ 错误: 未对可能为null的对象执行检查
- this.dbObject.executeSql(sql);
- // ✅ 正确: 执行null检查
- if (this.dbObject) {
- this.dbObject.executeSql(sql);
- }
- ```
- ### 2. 解构赋值规则
- ```typescript
- // ❌ 错误: ArkTS不支持解构赋值语法
- 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];
- // 处理逻辑
- }
- ```
- ### 3. 异步API调用规则
- ```typescript
- // ❌ 错误: 回调参数类型不匹配
- dbStore.executeSql(sql, (err, result: ResultSet) => {
- // 处理逻辑
- });
- // ✅ 正确: 使用Promise模式
- dbStore.executeSql(sql)
- .then(() => {
- // 成功处理
- })
- .catch((err: Error) => {
- // 错误处理
- console.log(err.message);
- });
- ```
- ### 4. 计算属性名规则
- ```typescript
- // ❌ 错误: 不支持计算属性名语法
- const obj = { [CONSTANT.KEY]: value };
- // ✅ 正确: 使用对象属性赋值语法
- const obj = {};
- obj[CONSTANT.KEY] = value;
- ```
- ### 5. 数据类型规则
- ```typescript
- // ❌ 错误: 使用any或未指定泛型类型
- const items = new Set();
- const map = new Map();
- // ✅ 正确: 明确指定泛型类型
- const items = new Set<string>();
- const map = new Map<string, number>();
- ```
- ### 6. 错误对象类型规则
- ```typescript
- // ❌ 错误: 使用隐式any类型的错误对象
- try {
- // 代码
- } catch (e) {
- console.log(`错误: ${e}`);
- }
- // ✅ 正确: 明确指定错误对象的类型
- try {
- // 代码
- } catch (e: Error) {
- console.log(`错误: ${e.message}`);
- }
- ```
- ### 7. 类型声明与对象字面量规则
- ```typescript
- // ❌ 错误: 对象字面量不能用作类型声明
- const metadataToUpdate: {
- duration?: string,
- mimeType?: string,
- sampleRate?: string,
- trackCount?: string
- } = { /* 值 */ };
- // ✅ 正确: 使用接口或类型别名定义类型
- interface MediaMetadata {
- duration?: string;
- mimeType?: string;
- sampleRate?: string;
- trackCount?: string;
- }
- const metadataToUpdate: MediaMetadata = { /* 值 */ };
- ```
- ## 数据库操作最佳实践
- ### 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) => { /* 错误处理 */ });
- });
- });
- ```
- ### 2. 资源释放
- ```typescript
- // ❌ 错误: 未关闭ResultSet
- this.rdbStore.query(predicates, (resultSet) => {
- // 处理逻辑
- });
- // ✅ 正确: 确保关闭ResultSet
- this.rdbStore.query(predicates, (resultSet) => {
- try {
- // 处理逻辑
- } finally {
- resultSet.close();
- }
- });
- ```
- ### 3. 数据库查询安全处理
- ```typescript
- // ❌ 错误: 不安全的列访问
- const value = resultSet.getString(resultSet.getColumnIndex(columnName));
- // ✅ 正确: 安全的列访问
- const safeGet = (col: string) => {
- const index = resultSet.getColumnIndex(col);
- return index >= 0 ? resultSet.getString(index) || '' : '';
- };
- const value = safeGet(columnName);
- ```
- ## 对象字面量规则
- ### 1. 复杂对象初始化
- ```typescript
- // ❌ 错误: 不支持复杂对象字面量初始化
- const config = {
- complex: {
- nested: {
- value: someValue
- }
- }
- };
- // ✅ 正确: 分步创建复杂对象
- const config = {};
- config.complex = {};
- config.complex.nested = {};
- config.complex.nested.value = someValue;
- ```
- ### 2. 接口实现
- ```typescript
- // ❌ 错误: 在类内部定义接口
- class MediaTable {
- interface MediaMetadata {
- duration?: string;
- mimeType?: string;
- }
- }
- // ✅ 正确: 在类外部定义接口并导出
- export interface MediaMetadata {
- duration?: string;
- mimeType?: string;
- }
- class MediaTable {
- // 类实现
- }
- ```
- ## UI数据处理规则
- ### 1. 空值处理
- ```typescript
- // ❌ 错误: 未处理空值或无效值
- Text(this.currentSong.sampleRate)
- // ✅ 正确: 安全处理空值和无效值
- Text(Utility.convertToKHz(this.currentSong?.sampleRate || ''))
- ```
- ### 2. 数据转换函数
- ```typescript
- // ❌ 错误: 直接在UI中转换数据
- Text(`${Number(this.sampleRate) / 1000} KHz`)
- // ✅ 正确: 使用工具函数处理数据格式化
- static convertToKHz(sampleRateHz: string|undefined): string {
- if(StrUtil.isEmpty(sampleRateHz) || sampleRateHz === undefined) {
- return '未知';
- }
-
- try {
- const sampleRateNum = Number(sampleRateHz);
- if (isNaN(sampleRateNum) || sampleRateNum <= 0) {
- return '未知';
- }
- return `${(sampleRateNum / 1000).toFixed(1)} KHz`;
- } catch (err) {
- return '未知';
- }
- }
- // 在UI中使用
- Text(Utility.convertToKHz(this.sampleRate))
- ```
- ## 命名规范
- - 类名: PascalCase (例如 MediaTable)
- - 方法名: camelCase (例如 queryByParentPath)
- - 常量: UPPER_SNAKE_CASE (例如 DB_COLUMNS.FILE_PATH)
- - 私有属性: _camelCase (例如 _dbStore)
- - 接口名: PascalCase带I前缀或不带 (例如 IMediaMetadata 或 MediaMetadata)
- ## 异步编程最佳实践
- ### 1. 避免回调地狱
- ```typescript
- // ❌ 错误: 嵌套回调
- methodA(() => {
- methodB(() => {
- methodC(() => {
- // 更多嵌套...
- });
- });
- });
- // ✅ 正确: 使用Promise链或async/await
- methodA()
- .then(() => methodB())
- .then(() => methodC())
- .catch(error => console.error(error));
- // 或使用async/await
- async function process() {
- try {
- await methodA();
- await methodB();
- await methodC();
- } catch (error) {
- console.error(error);
- }
- }
- ```
- ### 2. 异步状态更新
- ```typescript
- // ❌ 错误: 在异步回调中直接更新状态而没有检查组件是否已销毁
- fetchData(() => {
- this.data = result; // 组件可能已被销毁
- });
- // ✅ 正确: 添加组件生命周期检查
- fetchData(() => {
- if (!this.mDestroyPage) {
- this.data = result;
- }
- });
- ```
- ## 文件和代码组织
- ### 1. 导入导出规则
- ```typescript
- // ❌ 错误: 混合默认导出和命名导出
- export default class MediaTable { ... }
- export interface MediaMetadata { ... }
- // ✅ 正确: 明确区分默认导出和命名导出
- // MediaTable.ets
- export default class MediaTable { ... }
- // MediaTypes.ets
- export interface MediaMetadata { ... }
- export interface AudioMetadata extends MediaMetadata { ... }
- ```
- ### 2. 文件结构规则
- ```
- // ✅ 推荐的文件结构
- /common
- /constants // 常量定义
- /interfaces // 接口定义
- /util // 工具类
- /viewmodel // 视图模型
- /view // UI组件
- /controller // 控制器
- ```
|