1# 组件标识 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @pengzhiwen3--> 5<!--Designer: @lmleon--> 6<!--Tester: @fredyuan0912--> 7<!--Adviser: @HelloCrease--> 8 9id为组件的唯一标识,在整个应用内唯一。本模块提供组件标识相关接口,可以获取指定id组件的属性,也提供向指定id组件发送事件的功能。 10 11> **说明:** 12> 13> - 从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 14> 15> - 若同一个组件设置了多个id或者key,最后设置的生效。 16 17 18## id 19 20id(value: string): T 21 22组件的唯一标识,唯一性由使用者保证。当未设置id时,组件默认id为空。 23 24**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。 25 26**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 27 28**系统能力:** SystemCapability.ArkUI.ArkUI.Full 29 30**参数:** 31 32| 参数名 | 类型 | 必填 | 说明 | 33| ------ | -------- | -----|---------------------- | 34| value | string | 是 | 组件的唯一标识,唯一性由使用者保证。 | 35 36**返回值:** 37 38| 类型 | 说明 | 39| -------- | -------- | 40| T | 返回当前组件。 | 41 42## key<sup>12+</sup> 43 44key(value: string): T 45 46组件的唯一标识,唯一性由使用者保证。 47 48此接口仅用于对应用的测试。与id同时使用时,后赋值的属性会覆盖先赋值的属性,建议仅设置id。 49 50**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 51 52**系统能力:** SystemCapability.ArkUI.ArkUI.Full 53 54**参数:** 55 56| 参数名 | 类型 | 必填 | 说明 | 57| ------ | -------- | -----|---------------------- | 58| value | string | 是 | 组件的唯一标识,唯一性由使用者保证。<br>默认值:''<br/> | 59 60**返回值:** 61 62| 类型 | 说明 | 63| -------- | -------- | 64| T | 返回当前组件。 | 65 66## 基于组件标识的拓展能力 67 68组件标识的拓展能力仅用于对应用的测试,以下各个接口示例,需要在应用工程的ohosTest/ets/test目录中调试,具体可以参考<!--RP1-->[自动化测试框架使用指导](../../../../application-dev/application-test/arkxtest-guidelines.md)<!--RP1End-->。 69 70### getInspectorByKey<sup>9+</sup> 71 72getInspectorByKey(id: string): string 73 74获取指定id的组件的所有属性,不包括子组件信息。 75 76此接口仅用于对应用的测试,使用时建议等应用启动且布局完成后再调用此接口。由于耗时长,不建议测试之外的场景使用。 77 78**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 79 80**参数:** 81 82| 参数名 | 类型 | 必填 | 说明 | 83| ---- | -------- | ---- | -------------| 84| id | string | 是 | 要获取属性的组件id。 | 85 86**返回值:** 87 88| 类型 | 说明 | 89| -------| -------------- | 90| string | 组件属性列表的JSON字符串。<br />**说明**:<br /> 字符串信息包含组件的tag、id、位置信息(相对于窗口左上角的坐标)以及用于测试检查的组件所包含的相关属性信息。组件中每个字段的含义请参考[getInspectorInfo](../js-apis-arkui-frameNode.md#getinspectorinfo12)的返回值说明。 | 91 92**示例:** 93```ts 94@Entry 95@Component 96struct ComponentPage { 97 build() { 98 Column() { 99 Text("Hello World") 100 .fontSize(20) 101 .id("TEXT") 102 .onClick(() => { 103 console.info(`Text is clicked`); 104 }) 105 Button('TEST BUTTON').onClick(() => { 106 let result = getInspectorByKey("TEXT"); 107 console.info(`result is ${result}`); 108 }) 109 } 110 .width('100%') 111 .height('100%') 112 } 113} 114``` 115 116### getInspectorTree<sup>9+</sup> 117 118getInspectorTree(): Object 119 120获取组件树及组件属性。 121 122此接口仅用于对应用的测试。由于耗时长,不建议使用。 123 124**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 125 126**返回值:** 127 128| 类型 | 说明 | 129| ------ | --------------------------- | 130| Object | 组件树及组件属性列表的JSON对象。组件中每个字段的含义请参考[getInspectorInfo](../js-apis-arkui-frameNode.md#getinspectorinfo12)的返回值说明。 | 131 132**示例:** 133```ts 134@Entry 135@Component 136struct ComponentPage { 137 build() { 138 Column() { 139 Text("Hello World") 140 .fontSize(20) 141 .id("TEXT") 142 .onClick(() => { 143 console.info(`Text is clicked`); 144 }) 145 Button('TEST BUTTON').onClick(() => { 146 let result = getInspectorTree(); 147 console.info(`result is ${JSON.stringify(result)}`); 148 }) 149 } 150 .width('100%') 151 .height('100%') 152 } 153} 154``` 155 156### sendEventByKey<sup>9+</sup> 157 158sendEventByKey(id: string, action: number, params: string): boolean 159 160给指定id的组件发送事件。 161 162此接口仅用于对应用的测试。由于耗时长,不建议使用。 163 164**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 165 166**参数:** 167 168| 参数名 | 类型 | 必填 | 说明 | 169| ------ | -------| ---- | -------------------------- | 170| id | string | 是 | 要触发事件的组件的id。 | 171| action | number | 是 | 要触发的事件类型,目前支持取值:<br/>- 点击事件Click: 10。<br/>- 长按事件LongClick: 11。 | 172| params | string | 是 | 事件参数,无参数传空字符串 ""。 | 173 174**返回值:** 175 176| 类型 | 说明 | 177| -------- | --------------------------| 178| boolean | 找不到指定id的组件时返回false,其余情况返回true。 | 179 180**示例:** 181```ts 182@Entry 183@Component 184struct ComponentPage { 185 build() { 186 Column() { 187 Text("Hello World") 188 .fontSize(20) 189 .id("TEXT") 190 .onClick(() => { 191 console.info(`Text is clicked`); 192 }) 193 Button('TEST BUTTON').onClick(() => { 194 sendEventByKey("TEXT", 10, ""); 195 }) 196 } 197 .width('100%') 198 .height('100%') 199 } 200} 201``` 202 203### sendTouchEvent<sup>9+</sup> 204 205sendTouchEvent(event: TouchObject): boolean 206 207发送触摸事件。 208 209此接口仅用于对应用的测试。由于耗时长,不建议使用。 210 211**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 212 213**参数:** 214 215| 参数名 | 类型 | 必填 | 说明 | 216| ----- | ----------- | ---- | ------------------------------------------------------------ | 217| event | [TouchObject](ts-universal-events-touch.md#touchobject) | 是 | 触发触摸事件的位置,event参数见[TouchObject](ts-universal-events-touch.md#touchobject)的介绍。 | 218 219**返回值:** 220 221| 类型 | 说明 | 222| ------- | ---------------------------| 223| boolean | 事件发送失败时返回false,其余情况返回true。 | 224 225### sendKeyEvent<sup>9+</sup> 226 227sendKeyEvent(event: KeyEvent): boolean 228 229发送按键事件。 230 231此接口仅用于对应用的测试。由于耗时长,不建议使用。 232 233**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 234 235**参数:** 236 237| 参数名 | 类型 | 必填 | 说明 | 238| ----- | -------- | ---- | ------------------------------------------------------------ | 239| event | [KeyEvent](ts-universal-events-key.md#keyevent对象说明) | 是 | 按键事件,event参数见[KeyEvent](ts-universal-events-key.md#keyevent对象说明)介绍。 | 240 241**返回值:** 242 243| 类型 | 说明 | 244| ------- | ------------------------------| 245| boolean | 事件发送失败时时返回false,其余情况返回true。 | 246 247### sendMouseEvent<sup>9+</sup> 248 249sendMouseEvent(event: MouseEvent): boolean 250 251发送鼠标事件。 252 253此接口仅用于对应用的测试。由于耗时长,不建议使用。 254 255**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 256 257**参数:** 258 259| 参数名 | 类型 | 必填 | 说明 | 260| ----- | ---------- | ---- | --------------------------------------- | 261| event | [MouseEvent](ts-universal-mouse-key.md#mouseevent对象说明) | 是 | 鼠标事件,event参数见[MouseEvent](ts-universal-mouse-key.md#mouseevent对象说明)介绍。 | 262 263**返回值:** 264 265| 类型 | 说明 | 266| ------- | ---------------------------------- | 267| boolean | 事件发送失败时返回false,其余情况返回true。 | 268 269## 示例 270 271该示例主要展示如何通过组件标识接口,获取特定id组件的属性,以及如何向该id的组件触发事件。 272 273```ts 274// xxx.ets 275import { IntentionCode } from '@kit.InputKit'; 276 277class Utils { 278 static rect_left: number; 279 static rect_top: number; 280 static rect_right: number; 281 static rect_bottom: number; 282 static rect_value: Record<string, number>; 283 284 //获取组件所占矩形区域坐标 285 static getComponentRect(key:string):Record<string, number> { 286 let strJson = getInspectorByKey(key); 287 let obj:Record<string, string> = JSON.parse(strJson); 288 console.info("[getInspectorByKey] current component obj is: " + JSON.stringify(obj)); 289 let rectInfo:string[] = JSON.parse('[' + obj.$rect + ']'); 290 console.info("[getInspectorByKey] rectInfo is: " + rectInfo); 291 Utils.rect_left = JSON.parse('[' + rectInfo[0] + ']')[0]; // 相对于组件左上角的水平方向坐标 292 Utils.rect_top = JSON.parse('[' + rectInfo[0] + ']')[1]; // 相对于组件左上角的垂直方向坐标 293 Utils.rect_right = JSON.parse('[' + rectInfo[1] + ']')[0]; // 相对于组件右下角的水平方向坐标 294 Utils.rect_bottom = JSON.parse('[' + rectInfo[1] + ']')[1]; // 相对于组件右下角的垂直方向坐标 295 return Utils.rect_value = { 296 "left": Utils.rect_left, "top": Utils.rect_top, "right": Utils.rect_right, "bottom": Utils.rect_bottom 297 }; 298 }; 299} 300 301@Entry 302@Component 303struct IdExample { 304 @State text: string = ''; 305 306 build() { 307 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 308 309 Button() { 310 Text('onKeyTab').fontSize(25).fontWeight(FontWeight.Bold) 311 }.margin({ top: 20 }).backgroundColor('#0D9FFB') 312 .onKeyEvent(() => { 313 this.text = "onKeyTab"; 314 }) 315 316 Button() { 317 Text('click to start').fontSize(25).fontWeight(FontWeight.Bold) 318 }.margin({ top: 20 }) 319 .onClick(() => { 320 console.info(getInspectorByKey("click")); 321 console.info(JSON.stringify(getInspectorTree())); 322 this.text = "Button 'click to start' is clicked"; 323 setTimeout(() => { 324 sendEventByKey("longClick", 11, ""); // 向id为"longClick"的组件发送长按事件 325 }, 2000) 326 }).id('click') 327 328 Button() { 329 Text('longClick').fontSize(25).fontWeight(FontWeight.Bold) 330 }.margin({ top: 20 }).backgroundColor('#0D9FFB') 331 .gesture( 332 LongPressGesture().onActionEnd(() => { 333 console.info('long clicked'); 334 this.text = "Button 'longClick' is longclicked"; 335 setTimeout(() => { 336 let rect = Utils.getComponentRect('onTouch'); // 获取id为"onTouch"组件的矩形区域坐标 337 let touchPoint: TouchObject = { 338 id: 1, 339 type: TouchType.Down, 340 x: rect.left + (rect.right - rect.left) / 2, // 相对于组件左上角的水平方向坐标 341 y: rect.top + (rect.bottom - rect.top) / 2, // 相对于组件左上角的垂直方向坐标 342 screenX: rect.left + (rect.right - rect.left) / 2, // 相对于应用窗口左上角的水平方向坐标,API10已废弃,采用windowX替代 343 screenY: rect.top + (rect.bottom - rect.top) / 2, // 相对于应用窗口左上角的垂直方向坐标,API10已废弃,采用windowY替代 344 windowX: rect.left + (rect.right - rect.left) / 2, // 相对于应用窗口左上角的水平方向坐标 345 windowY: rect.top + (rect.bottom - rect.top), // 相对于应用窗口左上角的垂直方向坐标 346 displayX: rect.left + (rect.right - rect.left) / 2, // 相对于设备屏幕左上角的水平方向坐标 347 displayY: rect.top + (rect.bottom - rect.top) / 2, // 相对于设备屏幕左上角的垂直方向坐标 348 }; 349 sendTouchEvent(touchPoint); // 发送触摸事件 350 touchPoint.type = TouchType.Up; 351 sendTouchEvent(touchPoint); // 发送触摸事件 352 }, 2000) 353 })).id('longClick') 354 355 Button() { 356 Text('onTouch').fontSize(25).fontWeight(FontWeight.Bold) 357 }.type(ButtonType.Capsule).margin({ top: 20 }) 358 .onClick(() => { 359 console.info('onTouch is clicked'); 360 this.text = "Button 'onTouch' is clicked"; 361 setTimeout(() => { 362 let rect = Utils.getComponentRect('onMouse'); // 获取id为"onMouse"组件的矩形区域坐标 363 let mouseEvent: MouseEvent = { 364 button: MouseButton.Left, 365 action: MouseAction.Press, 366 x: rect.left + (rect.right - rect.left) / 2, // 相对于组件左上角的水平方向坐标 367 y: rect.top + (rect.bottom - rect.top) / 2, // 相对于组件左上角的垂直方向坐标 368 screenX: rect.left + (rect.right - rect.left) / 2, // 相对于应用窗口左上角的水平方向坐标,API10已废弃,采用windowX替代 369 screenY: rect.left + (rect.right - rect.left) / 2, // 相对于应用窗口左上角的垂直方向坐标,API10已废弃,采用windowY替代 370 windowX: rect.left + (rect.right - rect.left) / 2, // 相对于应用窗口左上角的水平方向坐标 371 windowY: rect.left + (rect.right - rect.left) / 2, // 相对于应用窗口左上角的垂直方向坐标 372 displayX: rect.left + (rect.right - rect.left) / 2, // 相对于设备屏幕左上角的水平方向坐标 373 displayY: rect.left + (rect.right - rect.left) / 2, // 相对于设备屏幕左上角的垂直方向坐标 374 stopPropagation: () => { 375 }, 376 timestamp: 1, 377 target: { 378 area: { 379 width: 1, 380 height: 1, 381 position: { 382 x: 1, 383 y: 1 384 }, 385 globalPosition: { 386 x: 1, 387 y: 1 388 } 389 } 390 }, 391 source: SourceType.Mouse, 392 pressure: 1, 393 tiltX: 1, 394 tiltY: 1, 395 sourceTool: SourceTool.Unknown 396 }; 397 sendMouseEvent(mouseEvent); // 发送鼠标事件 398 }, 2000) 399 }).id('onTouch') 400 401 Button() { 402 Text('onMouse').fontSize(25).fontWeight(FontWeight.Bold) 403 }.margin({ top: 20 }).backgroundColor('#0D9FFB') 404 .onMouse(() => { 405 console.info('onMouse'); 406 this.text = "Button 'onMouse' in onMouse"; 407 setTimeout(() => { 408 let keyEvent: KeyEvent = { 409 type: KeyType.Down, 410 keyCode: 2049, 411 keyText: 'tab', 412 keySource: 4, 413 deviceId: 0, 414 metaKey: 0, 415 timestamp: 0, 416 stopPropagation: () => { 417 }, 418 intentionCode: IntentionCode.INTENTION_DOWN 419 }; 420 sendKeyEvent(keyEvent); // 发送按键事件 421 }, 2000) 422 }).id('onMouse') 423 424 Text(this.text).fontSize(25).padding(15) 425 } 426 .width('100%').height('100%') 427 } 428} 429``` 430