1# NodeController 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @xiang-shouxing--> 5<!--Designer: @xiang-shouxing--> 6<!--Tester: @sally__--> 7<!--Adviser: @HelloCrease--> 8 9NodeController用于实现自定义节点的创建、显示、更新等操作的管理,并负责将自定义节点挂载到[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)上。 10 11> **说明:** 12> 13> 本模块首批接口从API version 11开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 14 15## 导入模块 16 17```ts 18import { NodeController } from '@kit.ArkUI'; 19``` 20 21## NodeController 22 23通常搭配[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)进行使用。用于创建控制器管理绑定的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)组件。一个NodeController只允许与一个[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)进行绑定。最佳实践请参考[组件动态创建-组件动态添加、更新和删除](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-ui-dynamic-operations#section153921947151012)。 24 25**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 26 27**系统能力:** SystemCapability.ArkUI.ArkUI.Full 28 29### makeNode 30 31abstract makeNode(uiContext : UIContext): FrameNode | null 32 33当实例绑定的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)创建的时候进行回调。回调方法将返回一个节点,将该节点挂载至[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)。 34或者可以通过NodeController的rebuild()方法进行回调的触发。 35 36**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 37 38**系统能力:** SystemCapability.ArkUI.ArkUI.Full 39 40**参数:** 41 42| 参数名 | 类型 | 必填 | 说明 | 43| --------- | ----------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------- | 44| uiContext | [UIContext](./arkts-apis-uicontext-uicontext.md) | 是 | 回调该方法的时候,绑定[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)的UI上下文。 | 45 46**返回值:** 47 48| 类型 | 说明 | 49| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 50| [FrameNode](./js-apis-arkui-frameNode.md)\| null | 一个FrameNode对象,返回的节点将被挂载至[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)的占位节点上。若返回null对象,将清空对应[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)的子节点。 | 51 52### aboutToAppear 53 54aboutToAppear?(): void 55 56当NodeController绑定的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)挂载显示后触发此回调。 57 58> **说明:** 59> 60> 回调时机参考[onAppear](arkui-ts/ts-universal-events-show-hide.md#onappear)。 61 62**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 63 64**系统能力:** SystemCapability.ArkUI.ArkUI.Full 65 66### aboutToDisappear 67 68aboutToDisappear?(): void 69 70当NodeController绑定的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)销毁时触发此回调。 71 72> **说明:** 73> 74> 回调时机参考[onDisAppear](arkui-ts/ts-universal-events-show-hide.md#ondisappear)。 75 76**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 77 78**系统能力:** SystemCapability.ArkUI.ArkUI.Full 79 80### onAttach<sup>18+</sup> 81 82onAttach?(): void 83 84当NodeController绑定的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)挂载至主节点树时触发此回调。 85 86> **说明:** 87> 88> 回调时机参考[onAttach](arkui-ts/ts-universal-events-show-hide.md#onattach12)。 89 90**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 91 92**系统能力:** SystemCapability.ArkUI.ArkUI.Full 93 94### onDetach<sup>18+</sup> 95 96onDetach?(): void 97 98当NodeController绑定的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)从主节点树卸载时触发此回调。 99 100> **说明:** 101> 102> 回调时机参考[onDetach](arkui-ts/ts-universal-events-show-hide.md#ondetach12)。 103 104**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 105 106**系统能力:** SystemCapability.ArkUI.ArkUI.Full 107 108### onWillBind<sup>18+</sup> 109 110onWillBind?(containerId: number): void 111 112当NodeController与[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)即将绑定前触发此回调。 113 114**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 115 116**系统能力:** SystemCapability.ArkUI.ArkUI.Full 117 118**参数:** 119 120| 参数名 | 类型 | 必填 | 说明 | 121| ----------- | ------ |----- |---------------------------------------------------------------------------------------------------------------------------------- | 122| containerId | number | 是 | 回调该方法时,NodeController与NodeContainerId对应的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)即将绑定。| 123 124### onWillUnbind<sup>18+</sup> 125 126onWillUnbind?(containerId: number): void 127 128当NodeController与[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)即将解绑前触发此回调。 129 130**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 131 132**系统能力:** SystemCapability.ArkUI.ArkUI.Full 133 134**参数:** 135 136| 参数名 | 类型 | 必填 | 说明 | 137| ----------- | ------ |----- |---------------------------------------------------------------------------------------------------------------------------------- | 138| containerId | number | 是 | 回调该方法时,NodeController与NodeContainerId对应的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)即将解绑。| 139 140### onBind<sup>18+</sup> 141 142onBind?(containerId: number): void 143 144当NodeController与[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)绑定后触发此回调。 145 146**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 147 148**系统能力:** SystemCapability.ArkUI.ArkUI.Full 149 150**参数:** 151 152| 参数名 | 类型 | 必填 | 说明 | 153| ----------- | ------ |----- |---------------------------------------------------------------------------------------------------------------------------------- | 154| containerId | number | 是 | 回调该方法时,NodeController与NodeContainerId对应的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)绑定完成。| 155 156### onUnbind<sup>18+</sup> 157 158onUnbind?(containerId: number): void 159 160当NodeController与[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)解绑后触发此回调。 161 162**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 163 164**系统能力:** SystemCapability.ArkUI.ArkUI.Full 165 166**参数:** 167 168| 参数名 | 类型 | 必填 | 说明 | 169| ----------- | ------ |----- |---------------------------------------------------------------------------------------------------------------------------------- | 170| containerId | number | 是 | 回调该方法时,NodeController与NodeContainerId对应的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)解绑完成。| 171 172### aboutToResize 173 174aboutToResize?(size: Size): void 175 176当NodeController绑定的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)布局的时候触发此回调。 177 178**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 179 180**系统能力:** SystemCapability.ArkUI.ArkUI.Full 181 182**参数:** 183 184| 参数名 | 类型 | 必填 | 说明 | 185| ------ | ---------------------------------------- | ---- | ---------------------------------------- | 186| size | [Size](./js-apis-arkui-graphics.md#size) | 是 | 用于返回组件布局大小的宽和高,单位为vp。 | 187 188### onTouchEvent 189 190onTouchEvent?(event: TouchEvent): void 191 192当NodeController绑定的[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)收到Touch事件时触发此回调。 193 194**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 195 196**系统能力:** SystemCapability.ArkUI.ArkUI.Full 197 198**参数:** 199 200| 参数名 | 类型 | 必填 | 说明 | 201| ------ | ------------------------------------------------------------------------- | ---- | ---------- | 202| event | [TouchEvent](arkui-ts/ts-universal-events-touch.md#touchevent对象说明) | 是 | 触摸事件。 | 203 204### rebuild 205 206rebuild(): void 207 208调用此接口通知[NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md)组件重新回调[makeNode](#makenode)方法,更改子节点。 209 210**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 211 212**系统能力:** SystemCapability.ArkUI.ArkUI.Full 213 214> **说明:** 215> 由于rebuild方法为应用主动调用的方法,且该操作与UI相关。需要开发者自行保证调用该接口时UI上下文有效,即与绑定的NodeContainer保持UI上下文一致。 216> 217> 监听回调等[UI上下文不明确](../../ui/arkts-global-interface.md#ui上下文不明确)时,可以通过[UIContext](./arkts-apis-uicontext-uicontext.md)的[runScopedTask](./arkts-apis-uicontext-uicontext.md#runscopedtask)方法明确调用时的UI上下文。 218 219## 示例 220 221### 示例1(添加节点布局、Touch、挂载和卸载时的生命周期回调) 222 223该示例通过aboutToResize、onTouchEvent,实现了NodeContainer节点布局、收到Touch事件时的生命周期回调功能。 224 225并通过aboutToAppear、aboutToDisappear接口,实现了NodeContainer节点挂载、卸载时的生命周期回调功能。 226 227通过NodeController挂载BuilderNode节点。 228 229```ts 230import { NodeController, BuilderNode, Size, FrameNode ,UIContext } from '@kit.ArkUI'; 231 232class Params { 233 text: string = "this is a text" 234} 235 236@Builder 237function buttonBuilder(params: Params) { 238 Column() { 239 Button(params.text) 240 .fontSize(12) 241 .borderRadius(8) 242 .borderWidth(2) 243 .backgroundColor(Color.Orange) 244 } 245} 246 247class MyNodeController extends NodeController { 248 private buttonNode: BuilderNode<[Params]> | null = null; 249 private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(buttonBuilder); 250 251 makeNode(uiContext: UIContext): FrameNode { 252 if (this.buttonNode == null) { 253 this.buttonNode = new BuilderNode(uiContext); 254 this.buttonNode.build(this.wrapBuilder, { text: "This is a Button" }) 255 } 256 return this.buttonNode!.getFrameNode()!; 257 } 258 259 aboutToResize(size: Size) { 260 console.info("aboutToResize width : " + size.width + " height : " + size.height) 261 } 262 263 aboutToAppear() { 264 console.info("aboutToAppear") 265 } 266 267 aboutToDisappear() { 268 console.info("aboutToDisappear"); 269 } 270 271 onTouchEvent(event:TouchEvent) { 272 console.info("onTouchEvent"); 273 } 274} 275 276@Entry 277@Component 278struct Index { 279 private myNodeController: MyNodeController = new MyNodeController(); 280 281 build() { 282 Column() { 283 NodeContainer(this.myNodeController) 284 } 285 .padding({ left: 35, right: 35, top: 35 }) 286 .width("100%") 287 .height("100%") 288 } 289} 290``` 291 292 293### 示例2(添加节点上下树和绑定解绑前后的生命周期回调) 294 295该示例通过onAttach、onDetach接口,实现了NodeContainer节点上下主节点树的生命周期回调功能。 296 297并通过onWillBind、onWillUnbind、onBind、onUnbind接口,实现了NodeContainer节点绑定和解绑前后的生命周期回调功能。 298 299```ts 300import { NodeController, BuilderNode, FrameNode, UIContext } from '@kit.ArkUI'; 301class Params { 302 text: string = "this is a text" 303} 304 305@Builder 306function buttonBuilder(params: Params) { 307 Column() { 308 Button(params.text) 309 .fontSize(20) 310 .borderRadius(8) 311 .borderWidth(2) 312 .backgroundColor(Color.Grey) 313 } 314} 315 316class MyNodeController extends NodeController { 317 private buttonNode: BuilderNode<[Params]> | null = null; 318 private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(buttonBuilder); 319 320 makeNode(uiContext: UIContext): FrameNode { 321 if (this.buttonNode == null) { 322 this.buttonNode = new BuilderNode(uiContext); 323 this.buttonNode.build(this.wrapBuilder, { text: "This is a Button" }) 324 } 325 return this.buttonNode!.getFrameNode()!; 326 } 327 328 onAttach(): void { 329 console.info("myButton on attach"); 330 } 331 332 onDetach(): void { 333 console.info("myButton on detach"); 334 } 335 336 onWillBind(containerId: number): void{ 337 console.info("myButton on WillBind" + containerId); 338 } 339 340 onWillUnbind(containerId: number): void{ 341 console.info("myButton on WillUnbind" + containerId); 342 } 343 344 onBind(containerId: number): void { 345 console.info("myButton on bind: " + containerId); 346 } 347 348 onUnbind(containerId: number): void { 349 console.info("myButton on unbind: " + containerId); 350 } 351} 352 353@Entry 354@Component 355struct Index { 356 @State buttonShow: boolean = true 357 @State buttonIndex: number = 0 358 private buttonController: MyNodeController = new MyNodeController(); 359 private buttonNull: null = null; 360 private buttonControllerArray: Array < MyNodeController | null > = [this.buttonController,this.buttonNull] 361 362 build() { 363 Column() { 364 Row(){ 365 Button("Bind/Unbind") 366 .onClick(() => { 367 this.buttonIndex++; 368 }).margin(5) 369 Button("onAttach/onDetach") 370 .onClick(() => { 371 this.buttonShow = !this.buttonShow 372 }).margin(5) 373 } 374 if(this.buttonShow){ 375 NodeContainer(this.buttonControllerArray[this.buttonIndex % this.buttonControllerArray.length]) 376 } 377 } 378 .padding({ left: 35, right: 35}) 379 .width("100%") 380 .height("100%") 381 } 382} 383``` 384 385 386