cursorrules.mdc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. # 鸿蒙ArkTS编程规则与最佳实践
  2. ## 语法差异规则:ArkTS vs TypeScript
  3. ### 1. 空值检查规则
  4. ```typescript
  5. // ❌ 错误: 未对可能为null的对象执行检查
  6. this.dbObject.executeSql(sql);
  7. // ✅ 正确: 执行null检查
  8. if (this.dbObject) {
  9. this.dbObject.executeSql(sql);
  10. }
  11. ```
  12. ### 2. 解构赋值规则(已支持)
  13. ```typescript
  14. // ✅ 正确: ArkTS 4.0+ 已支持解构赋值语法
  15. for (const [key, value] of Object.entries(obj)) {
  16. // 处理逻辑
  17. }
  18. // ✅ 正确: 数组解构赋值
  19. const [first, second, ...rest] = array;
  20. // ✅ 正确: 对象解构赋值
  21. const { name, age, ...otherProps } = person;
  22. ```
  23. ### 3. 异步API调用规则
  24. ```typescript
  25. // ❌ 错误: 回调参数类型不匹配
  26. dbStore.executeSql(sql, (err, result: ResultSet) => {
  27. // 处理逻辑
  28. });
  29. // ✅ 正确: 使用Promise模式
  30. dbStore.executeSql(sql)
  31. .then(() => {
  32. // 成功处理
  33. })
  34. .catch((err: Error) => {
  35. // 错误处理
  36. console.log(err.message);
  37. });
  38. // ✅ 正确: 使用async/await模式
  39. async function executeQuery() {
  40. try {
  41. await dbStore.executeSql(sql);
  42. // 成功处理
  43. } catch (err: Error) {
  44. // 错误处理
  45. console.log(err.message);
  46. }
  47. }
  48. ```
  49. ### 4. 计算属性名规则(已支持)
  50. ```typescript
  51. // ✅ 正确: ArkTS 4.0+ 已支持计算属性名语法
  52. const obj = { [CONSTANT.KEY]: value };
  53. // ✅ 正确: 动态属性名
  54. const propertyName = 'dynamicKey';
  55. const obj = { [propertyName]: value };
  56. ```
  57. ### 5. 数据类型规则
  58. ```typescript
  59. // ❌ 错误: 使用any或未指定泛型类型
  60. const items = new Set();
  61. const map = new Map();
  62. // ✅ 正确: 明确指定泛型类型
  63. const items = new Set<string>();
  64. const map = new Map<string, number>();
  65. // ✅ 正确: 使用类型推断
  66. const items = new Set<string>();
  67. const map = new Map<string, number>();
  68. ```
  69. ### 6. 错误对象类型规则
  70. ```typescript
  71. // ❌ 错误: 使用隐式any类型的错误对象
  72. try {
  73. // 代码
  74. } catch (e) {
  75. console.log(`错误: ${e}`);
  76. }
  77. // ✅ 正确: 明确指定错误对象的类型
  78. try {
  79. // 代码
  80. } catch (e: Error) {
  81. console.log(`错误: ${e.message}`);
  82. }
  83. // ✅ 正确: 使用unknown类型(更安全)
  84. try {
  85. // 代码
  86. } catch (e: unknown) {
  87. if (e instanceof Error) {
  88. console.log(`错误: ${e.message}`);
  89. } else {
  90. console.log(`未知错误: ${e}`);
  91. }
  92. }
  93. ```
  94. ### 7. 新的语法特性支持
  95. #### 7.1 可选链操作符
  96. ```typescript
  97. // ✅ 正确: 使用可选链操作符
  98. const name = user?.profile?.name;
  99. const result = obj?.method?.();
  100. ```
  101. #### 7.2 空值合并操作符
  102. ```typescript
  103. // ✅ 正确: 使用空值合并操作符
  104. const value = input ?? defaultValue;
  105. const name = user?.name ?? 'Unknown';
  106. ```
  107. #### 7.3 模板字面量
  108. ```typescript
  109. // ✅ 正确: 使用模板字面量
  110. const message = `Hello, ${name}!`;
  111. const sql = `SELECT * FROM ${tableName} WHERE id = ${id}`;
  112. ```
  113. ## 数据库操作最佳实践
  114. ### 1. 表结构升级
  115. ```typescript
  116. // ❌ 错误: 依赖回调处理的表结构升级
  117. this.rdbStore.executeSql(tableInfoQuery, (err, result) => {
  118. // 处理逻辑
  119. });
  120. // ✅ 正确: 使用Promise模式并独立处理每个列的添加操作
  121. this.rdbStore.executeSql(tableInfoQuery)
  122. .then(() => {
  123. // 为每个需要添加的列单独执行ALTER TABLE
  124. Object.keys(columnsToAdd).forEach(column => {
  125. const type = columnsToAdd[column];
  126. this.rdbStore.executeSql(`ALTER TABLE ${tableName} ADD COLUMN ${column} ${type}`)
  127. .then(() => { /* 成功处理 */ })
  128. .catch((err: Error) => { /* 错误处理 */ });
  129. });
  130. });
  131. // ✅ 正确: 使用async/await模式
  132. async function upgradeTable() {
  133. try {
  134. await this.rdbStore.executeSql(tableInfoQuery);
  135. for (const [column, type] of Object.entries(columnsToAdd)) {
  136. await this.rdbStore.executeSql(`ALTER TABLE ${tableName} ADD COLUMN ${column} ${type}`);
  137. }
  138. } catch (err: Error) {
  139. console.error('表结构升级失败:', err.message);
  140. }
  141. }
  142. ```
  143. ### 2. 资源释放
  144. ```typescript
  145. // ❌ 错误: 未关闭ResultSet
  146. this.rdbStore.query(predicates, (resultSet) => {
  147. // 处理逻辑
  148. });
  149. // ✅ 正确: 确保关闭ResultSet
  150. this.rdbStore.query(predicates, (resultSet) => {
  151. try {
  152. // 处理逻辑
  153. } finally {
  154. resultSet.close();
  155. }
  156. });
  157. // ✅ 正确: 使用async/await模式
  158. async function queryData() {
  159. const resultSet = await this.rdbStore.query(predicates);
  160. try {
  161. // 处理逻辑
  162. } finally {
  163. resultSet.close();
  164. }
  165. }
  166. ```
  167. ## 对象字面量规则
  168. ### 1. 复杂对象初始化(已支持)
  169. ```typescript
  170. // ✅ 正确: ArkTS 4.0+ 已支持复杂对象字面量初始化
  171. const config = {
  172. complex: {
  173. nested: {
  174. value: someValue
  175. }
  176. }
  177. };
  178. // ✅ 正确: 使用展开操作符
  179. const baseConfig = { timeout: 5000 };
  180. const extendedConfig = { ...baseConfig, retries: 3 };
  181. ```
  182. ### 2. 方法简写
  183. ```typescript
  184. // ✅ 正确: 使用方法简写语法
  185. const obj = {
  186. name: 'test',
  187. sayHello() {
  188. return `Hello, ${this.name}!`;
  189. }
  190. };
  191. ```
  192. ## 组件开发最佳实践
  193. ### 1. 状态管理
  194. ```typescript
  195. // ✅ 正确: 使用@State装饰器
  196. @State count: number = 0;
  197. // ✅ 正确: 使用@Prop装饰器
  198. @Prop title: string = '';
  199. // ✅ 正确: 使用@Link装饰器
  200. @Link isVisible: boolean = false;
  201. ```
  202. ### 2. 生命周期方法
  203. ```typescript
  204. // ✅ 正确: 使用async生命周期方法
  205. async aboutToAppear() {
  206. await this.initializeData();
  207. }
  208. // ✅ 正确: 使用Promise处理异步操作
  209. aboutToAppear() {
  210. this.initializeData().then(() => {
  211. console.log('初始化完成');
  212. }).catch((err: Error) => {
  213. console.error('初始化失败:', err.message);
  214. });
  215. }
  216. ```
  217. ### 3. 事件处理
  218. ```typescript
  219. // ✅ 正确: 使用async事件处理
  220. .onClick(async () => {
  221. try {
  222. await this.handleClick();
  223. } catch (err: Error) {
  224. console.error('点击处理失败:', err.message);
  225. }
  226. })
  227. // ✅ 正确: 使用箭头函数
  228. .onClick((event: ClickEvent) => {
  229. this.handleClick(event);
  230. })
  231. ```
  232. ## 性能优化最佳实践
  233. ### 1. 避免在build方法中进行复杂计算
  234. ```typescript
  235. // ❌ 错误: 在build方法中进行复杂计算
  236. build() {
  237. const expensiveResult = this.computeExpensiveValue();
  238. return Column() {
  239. Text(expensiveResult)
  240. }
  241. }
  242. // ✅ 正确: 预先计算或使用缓存
  243. @State private cachedResult: string = '';
  244. aboutToAppear() {
  245. this.cachedResult = this.computeExpensiveValue();
  246. }
  247. build() {
  248. return Column() {
  249. Text(this.cachedResult)
  250. }
  251. }
  252. ```
  253. ### 2. 使用LazyForEach优化列表性能
  254. ```typescript
  255. // ✅ 正确: 使用LazyForEach
  256. LazyForEach(this.dataSource, (item: DataItem) => {
  257. ListItem() {
  258. Text(item.name)
  259. }
  260. }, (item: DataItem) => item.id.toString())
  261. ```
  262. ## 命名规范
  263. - 类名: PascalCase (例如 MediaTable)
  264. - 方法名: camelCase (例如 queryByParentPath)
  265. - 常量: UPPER_SNAKE_CASE (例如 DB_COLUMNS.FILE_PATH)
  266. - 私有属性: _camelCase (例如 _dbStore)
  267. - 组件名: PascalCase (例如 NewIndex)
  268. - 装饰器: @开头 (例如 @State, @Prop)
  269. ## 错误处理最佳实践
  270. ### 1. 统一错误处理
  271. ```typescript
  272. // ✅ 正确: 创建统一的错误处理函数
  273. private handleError(error: unknown, context: string): void {
  274. if (error instanceof Error) {
  275. console.error(`${context} 失败:`, error.message);
  276. } else {
  277. console.error(`${context} 失败:`, String(error));
  278. }
  279. }
  280. // 使用示例
  281. try {
  282. await this.performOperation();
  283. } catch (error: unknown) {
  284. this.handleError(error, '操作执行');
  285. }
  286. ```
  287. ### 2. 业务错误处理
  288. ```typescript
  289. // ✅ 正确: 处理业务错误
  290. try {
  291. await this.apiCall();
  292. } catch (error: unknown) {
  293. if (error instanceof BusinessError) {
  294. console.error(`业务错误: ${error.code}, ${error.message}`);
  295. } else {
  296. console.error('未知错误:', error);
  297. }
  298. }
  299. ```
  300. ## 类型安全最佳实践
  301. ### 1. 使用类型断言
  302. ```typescript
  303. // ✅ 正确: 安全的类型断言
  304. const result = data as VideoItem;
  305. // ✅ 正确: 使用类型守卫
  306. if (typeof data === 'object' && data !== null && 'name' in data) {
  307. const videoItem = data as VideoItem;
  308. }
  309. ```
  310. ### 2. 接口定义
  311. ```typescript
  312. // ✅ 正确: 定义清晰的接口
  313. interface VideoItem {
  314. id: string;
  315. name: string;
  316. artist?: string;
  317. album?: string;
  318. duration: number;
  319. filePath: string;
  320. }
  321. ```
  322. ## 调试和日志最佳实践
  323. ### 1. 使用hilog进行日志记录
  324. ```typescript
  325. // ✅ 正确: 使用hilog
  326. import hilog from '@ohos.hilog';
  327. hilog.info(0x0000, 'TAG', '%{public}s', '信息日志');
  328. hilog.warn(0x0000, 'TAG', '%{public}s', '警告日志');
  329. hilog.error(0x0000, 'TAG', '%{public}s', '错误日志');
  330. ```
  331. ### 2. 条件日志
  332. ```typescript
  333. // ✅ 正确: 使用条件日志避免性能影响
  334. if (__DEV__) {
  335. console.log('调试信息:', data);
  336. }
  337. ```
  338. - 私有属性: _camelCase (例如 _dbStore)