鸿蒙开发入门day17-使用自定义能力

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,还请三连支持一波哇ヾ(@^∇^@)ノ)

目录

自定义能力概述

自定义能力分层

自定义能力导览

自定义节点

自定义节点概述

自定义占位节点

FrameNode

RenderNode

BuilderNode

自定义占位节点

NodeContainer和NodeController

FrameNode

概述

创建和删除节点

判断节点是否可修改

获取对应的RenderNode节点

操作节点树

设置节点通用属性和事件回调

自定义测量布局与绘制

查找节点及获取基础信息

RenderNode

概述

创建和删除节点

操作节点树

设置和获取渲染相关属性

自定义绘制

BuilderNode

概述

创建BuilderNode对象

创建原生组件树

更新原生组件树

解除实体节点引用关系

注入触摸事件


自定义能力概述

自定义能力分层

自定义能力是ArkUI开发框架提供的对UI界面进行开发和定制化的能力。ArkUI开发框架提供的不同控制层级的自定义能力用于实现不同场景的应用的开发。自定义能力的开放层次越低,表示越接近底层基础能力,开发的灵活程度越高,开发难度越高、对于开发者能力的要求也越高。

当前开放的自定义能力包括以下几个层次:

  • 自定义组合:ArkUI框架提供的最基础的自定义方式,通过内置组件和自定义组件的基础能力,将这些能力进行组合,复用已有组件,进一步封装新的组件。具体包括:封装、布局、绘制和动画等基础能力。
  • 自定义扩展 :ArkUI框架提供一系列Modifier的能力,通过与UI分离的方式,对已有UI组件的属性、手势、内容进行扩展修改。包括AttributeModifierGestureModifierDrawModifier等扩展能力。
  • 自定义节点 :具备底层实体节点的部分基础能力的节点对象,这些节点能够通过自定义占位节点与原生组件进行混合显示。自定义节点可以具备单个节点的测算布局、设置基础属性、设置事件监听、自定义绘制渲染内容的自定义能力。包括FrameNodeRenderNodeBuilderNode三类对象。
  • 自定义渲染 :通过XComponent的"surface"模式暴露出的NativeWindow,使用NDK接口,可以将EGL/OpenGLES生成的显示数据或其它方式解码生成的媒体流数据写入到NativeWindow中,可以实现渲染内容的自定义。

自定义能力导览

上述提到自定义能力层次不同,使用场景也不同。通过以下导览,可快速了解各种自定义能力的说明以及使用场景和建议。

自定义层次 自定义能力 能力说明及适用场景
自定义组合 自定义封装 @Component装饰器:提供了最基础的组件封装能力,通过组合已有组件封装为新的自定义组件。 @Builder装饰器:提供更轻量的UI封装和复用机制,可以将重复使用的UI结构抽象成一个Builder方法,在组件的build方法中调用。
自定义组合 自定义布局 层叠布局(Stack):通过Stack容器,结合尺寸设置位置设置的通用属性,可对子组件进行自定义的排布。适用于子组件明确、相对简单的布局场景。 自定义组件的自定义布局:通过自定义组件的布局生命周期回调方法,对组件内子组件的位置进行调整。适用于封装一个特定布局算法的自定义组件。
自定义组合 自定义绘制 Canvas组件:通过Canvas组件的能力进行自定义绘制,通过组合的方式集成到自定义组件中,其接口和W3C标准的Canvas接口相近,在性能不敏感的场景下,适用于熟悉Web开发的开发者,可用于移植基于W3C的Canvas的绘制库。 Shape类组件:通过基础的图形类组件(RectPathCircleEllipsePolylinePolygon)进行组合,构建出自定义的图形。类似SVG矢量图的能力,适用于比较简单的图形组合,并可以结合动画的能力,实现一些交互的图形动画。
自定义组合 自定义动画 属性动画:对于组件的可动画属性,通过属性动画的能力,可组合实现自定义的动画效果。 @AnimatableExtend装饰器:对于组件的不可动画属性,通过@AnimatableExtend装饰器,使不可动画属性能实现自定义动画效果。 @ohos.animator 接口:通过动画接口可实现逐帧修改属性或结合自定义绘制的能力,实现类似帧动画的自定义动画效果。
自定义扩展 属性扩展 AttributeModifier:通过AttributeModifier可以实现UI与样式分离,实现属性、事件的动态设置与更新,同时支持跨文件的导出与复用。可用于组件封装,通过暴露Modifier实现属性的扩展。 自定义Modifier:通过框架提供封装的组件Modifier类,直接在Modifier对象上暴露的组件的属性和方法,可以简化组件封装时属性的传递与扩展。 AttributeUpdater:在AttributeModifier的基础之上增加了直接设置属性的能力,避免通过状态变量更新带来的性能损耗。适用于大量组件频繁更新某些属性的场景,提升属性设置的性能。
自定义扩展 手势扩展 GestureModifier:与AttributeModifier的能力类似,支持对手势进行扩展,动态的添加、删除手势,同样可以支持跨文件的导出与复用。适用于需要对自定义手势处理的通用逻辑进行封装和复用的场景。
自定义扩展 内容扩展 DrawModifier:通过DrawModifier可以在原生组件的基础之上,扩展叠加绘制自定义的内容,或者完全替换组件默认的绘制内容。 ContentModifier:在一些内容区和交互明确的内置组件上,通过ContentModifier可以实现使用自定义的Builder方法替换组件的内容。
自定义节点 组件节点 FrameNode: 表示组件的实体节点,主要提供以下两类能力: 完全自定义节点能力:提供完整的自定义能力,包括自定义测量、布局以及绘制,支持节点的动态增加、删除,并且可以为节点设置通用属性和事件。适用于不带渲染引擎,但需要依赖系统的布局、事件、动画及渲染等能力,实现语言为高级语言的三方框架对接。 组件代理节点能力:提供声明式组件的代理能力,提供遍历节点树的能力,通过FrameNode可以遍历整个组件树,并通过节点访问组件的信息或者注册额外的事件监听回调。适用于结合无感监听的接口实现打点、广告SDK、中台DFX等业务。 TypedFrameNode:通过typeNode提供的接口,可创建具体类型的FrameNode能力。创建出具体组件类型的FrameNode,可通过FrameNode的接口,进行自定义的挂载,生成一棵自定义的组件树。适用于高效对接高级语言开发的动态化框架。
自定义节点 渲染节点 RenderNode:表示轻量级的渲染节点RenderNode,仅提供了设置渲染相关属性、自定义绘制内容以及节点操作的能力。可以向三方框架提供基础的渲染、动画能力。适用于不带渲染引擎,只依赖系统的基础动画、渲染的三方框架对接。
自定义节点 原生组件混合 BuilderNode:BuilderNode对象提供了能够创建、更新原生组件以及组件树的能力。用于在自定义的FrameNode或RenderNode树结构中嵌入声明式的组件结构,实现原生组件与自定义节点的混合显示。另外还提供了对Builder内容进行纹理导出的能力,可实现在XComponent创建的渲染环境中进行同层渲染显示。
自定义渲染 独立渲染 XComponent:XComponent的"surface"模式会暴露出NativeWindow,通过NDK接口配合NativeWindow可创建独立的渲染环境,将EGL/OpenGLES生成的显示数据或其它方式解码生成的媒体流数据写入到NativeWindow中,不依赖ArkUI框架提供的其它组件能力即可进行自定义的渲染。适用于自带渲染引擎的框架,如游戏引擎、地图、相机等场景。

自定义节点

自定义节点概述

自定义节点是ArkUI框架通过接口提供了底层实体节点部分基础能力的节点对象,这些节点能够与原生控件进行混合显示。

自定义节点的挂载和显示需要依赖自定义占位节点。现有的自定义节点包括FrameNodeRenderNodeBuilderNode三类对象。FrameNode表示了单个的自定义组件节点,RenderNode表示更加轻量级的渲染节点,BuilderNode对象提供了能够创建、更新原生组件以及组件树的能力。

自定义占位节点

自定义占位节点作为原生组件可以在原生组件树上为自定义节点提供挂载的点。通过自定义占位节点,可以将自定义节点挂载在占位节点上,实现自定义节点与原生组件的混合显示。

FrameNode

FrameNode表示组件的实体节点,具体可以分为两大类能力:完全自定义节点的能力以及原生组件节点代理的能力。

  • 完全自定义节点:提供完整的自定义能力,包括自定义测量、布局以及绘制,支持节点的动态增、删,设置通用属性,设置事件回调。适用于不自带渲染引擎,需要依赖系统的布局、事件、动画、渲染等能力的场景。

  • 原生组件代理节点:提供原生组件的代理能力,提供遍历节点树的能力,通过组件树上的FrameNode可以遍历整个组件树,并通过节点访问组件的信息或者注册额外的事件监听回调。适用于结合无感监听的接口实现打点、广告SDK、中台DFX等业务。

RenderNode

RenderNode作为轻量级的渲染节点,仅提供了设置渲染相关属性、自定义绘制内容以及节点操作的能力。适用于仅依赖系统渲染与动画能力的自定义场景。

BuilderNode

BuilderNode通过无状态的UI方法全局@Builder生成组件树,组件树内的节点为原生组件。适用于需要基于系统能力创建特定原生组件树与其他自定义节点进行混合显示的场景。相比较原生组件,BuilderNode具备预创建的优势,可以控制开始创建的时间。由于持有实体节点对象,因此可以同步实现节点的复用,通过占位节点结合FrameNode、RenderNode的节点操作能力控制显示位置。

自定义占位节点

ArkUI提供了ArkTS原生组件作为自定义节点的占位节点。该占位节点具备组件的通用属性。

NodeContainer和NodeController

NodeContainer作为原生组件,仅具备组件的通用属性,其节点规格参考默认左上角对齐的Stack组件。NodeContainer作为一个占位容器组件,主要是用于显示自定义节点以及自定义节点树的显示和复用。

NodeController提供了一系列生命周期回调,通过makeNode回调返回一个FrameNode节点树的根节点。将FrameNode节点树挂载到对应的NodeContainer下。同时提供了aboutToAppear、aboutToDisappear、aboutToResize、onTouchEvent、rebuild五个回调方法用于监听对应的NodeContainer的状态。

每个生命周期的回调的具体含义参考NodeController的接口文档说明。
说明

  • NodeContainer下仅支持挂载自定义的FrameNode节点以及BuilderNode创建的组件树的根节点。

  • 从API Version 12开始支持的接口,可以通过FrameNode的查询接接口返回原生组件的代理节点,代理节点可以作为makeNode的返回值进行返回,但代理节点无法成功挂载在组件树上,最终的显示结果为代理节点挂载失败。

  • 需要保证一个节点只能作为一个父节点的子节点去使用,否则可能存在显示异常或者功能异常,尤其是页面路由场景或者动效场景。例如,如果通过NodeController将同一个节点挂载在多个NodeContainer上,仅一个占位容器下会显示节点,且多个NodeContainer的可见性、透明度等影响子组件状态的属性更新均会影响被挂载的子节点。

TypeScript 复制代码
import { BuilderNode, FrameNode, NodeController, Size, UIContext } from '@kit.ArkUI'

class Params {
  text: string = "this is a text"
}

@Builder
function buttonBuilder(params: Params) {
  Column() {
    Button(params.text)
      .fontSize(12)
      .borderRadius(8)
      .borderWidth(2)
      .backgroundColor(Color.Orange)
  }
}

let buttonNode: BuilderNode<[Params]> | null = null;

class MyNodeController extends NodeController {
  private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(buttonBuilder);
  private isShow: boolean = false;

  constructor(isShow: boolean) {
    super();
    this.isShow = isShow;
  }

  makeNode(uiContext: UIContext): FrameNode | null {
    if (!this.isShow) {
      return null;
    }
    if (buttonNode == null) {
      buttonNode = new BuilderNode<[Params]>(uiContext);
      buttonNode.build(this.wrapBuilder, { text: "This is a Button" })
    }
    let frameNode = buttonNode?.getFrameNode();
    return frameNode ? frameNode : null;
  }

  aboutToResize(size: Size) {
    console.log("aboutToResize width : " + size.width + " height : " + size.height)
  }

  aboutToAppear() {
    console.log("aboutToAppear")
  }

  aboutToDisappear() {
    console.log("aboutToDisappear");
  }

  onTouchEvent(event: TouchEvent) {
    console.log("onTouchEvent");
  }

  toShow() {
    this.isShow = true;
    this.rebuild();
  }

  toHide() {
    this.isShow = false;
    this.rebuild();
  }
}

@Entry
@Component
struct Index {
  private myNodeController1: MyNodeController = new MyNodeController(true);
  private myNodeController2: MyNodeController = new MyNodeController(false);

  build() {
    Column() {
      NodeContainer(this.myNodeController1)
        .width("100%")
        .height("40%")
        .backgroundColor(Color.Brown)
      NodeContainer(this.myNodeController2)
        .width("100%")
        .height("40%")
        .backgroundColor(Color.Gray)
      Button("Change the place of button")
        .onClick(() => {
          // 先在原始占位节点中下树
          // 后在新的占位节点中上树
          // 保证自定义节点仅作为一个节点的子节点存在
          this.myNodeController1.toHide();
          this.myNodeController2.toShow();
        })
    }
    .padding({ left: 35, right: 35, top: 35 })
    .width("100%")
    .height("100%")
  }
}

FrameNode

概述

对于具备自己前端定义的三方框架,需要将特定的dsl转换成为ArkUI的声明式描述。这个转换过程需依赖额外的数据驱动绑定至Builder中,转换比较复杂且性能较低。这一类框架一般依赖系统ArkUI框架的布局、事件能力,以及最基础的节点操作和自定义能力,大部分组件通过自定义完成,但是需要使用部分原生组件混合显示。FrameNode的设计就是为了解决上述的问题。

FrameNode表示组件树的实体节点,配合自定义占位容器组件NodeContainer等,在占位容器内挂载一棵自定义的节点树,并对这个节点树中的节点进行动态的增加、修改、删除等操作。基础的FrameNode可以设置通用属性、设置事件回调,并提供完整的自定义能力,包括自定义测量、布局以及绘制。

除此之外,ArkUI框架还提供获取和遍历获得原生组件对应的代理FrameNode对象的能力,下文简称代理节点。代理节点可以用于需要遍历整个UI的树形结构,并支持获取原生组件节点的具体信息或者额外注册组件的事件监听回调。

创建和删除节点

FrameNode提供了节点创建和删除的能力。可以通过FrameNode的构造函数创建自定义FrameNode节点,通过构造函数创建的节点对应一个实体的节点。同时,可以通过FrameNode中的dispose接口来实现与实体节点的绑定关系的解除。

说明

  • 在创建FrameNode对象的时候需要传入必选参数UIContext,若未传入UIContext对象或者传入不合法,则节点创建抛出异常。

  • 自定义占位组件将节点进行显示的时候需要保证UI上下文一致,否则会出现显示异常。

  • 若不持有FrameNode对象,则该对象会在GC的时候被回收。

判断节点是否可修改

isModifiable用于查询当前节点类型是否为原生组件的代理节点。当FrameNode节点作为原生组件的代理节点的时候,该节点不可修改。即无法修改代理节点的自身属性以及其子节点的结构。

获取对应的RenderNode节点

FrameNode提供了getRenderNode接口,用于获取FrameNode中的RenderNode。可以通过对获取到的RenderNode对象进行操作,动态修改FrameNode上绘制相关的属性,具体可修改的属性参考RenderNode的接口。

说明

  • 无法获取原生组件代理FrameNode的RenderNode对象。

  • BuilderNode中调用getFrameNode获取得到的FrameNode节点对象中,可以通过getRenderNode获取对应的根节点的RenderNode对象。

操作节点树

FrameNode提供了节点的增、删、查、改的能力,能够修改非代理节点的子树结构;可以对所有FrameNode的节点的父子节点做出查询操作,并返回查询结果。

说明

对节点进行增、删、改操作的时候,会对非法操作抛出异常信息。

通过查询获得的原生组件的代理节点,仅具备查询节点信息的作用,不具备修改节点属性的功能;代理节点不持有组件的实体节点,即不影响对应的节点的生命周期。

查询节点仅查询获得UI相关的节点,不返回语法节点。

使用自定义组件的场景下,可能查询获得自定义组件的新增节点,节点类型为"Common"。

设置节点通用属性和事件回调

FrameNode提供了commonAttributecommonEvent两个对象用于对设置节点的通用属性设置事件回调

说明

  • 由于代理节点的属性不可修改,因此通过代理节点的commonAttribute修改节点的基础属性不生效。

  • 设置的基础事件与原生组件定义的事件平行,参与事件竞争;设置的基础事件不覆盖原生组件事件。同时设置两个事件回调的时候,优先回调原生组件事件。

自定义测量布局与绘制

通过重写onDraw方法,可以自定义FrameNode的绘制内容。invalidate接口可以主动触发节点的重新绘制。

通过重写onMeasure可以自定义FrameNode的测量方式,使用measure可以主动传递布局约束触发重新测量。

通过重写onLayout方法可以自定义FrameNode的布局方式,使用layout方法可以主动传递位置信息并触发重新布局。

setNeedsLayout可以将当前节点标记,在下一帧触发重新布局。

说明

  • 对节点进行dispose解引用后,由于FrameNode对象不再对应一个实体节点,invalidate无法触发原有绑定节点的刷新。

  • 通过onDraw方法进行的自定义绘制,绘制内容大小无法超出组件大小。

查找节点及获取基础信息

FrameNode提供了查询接口用于返回实体节点的基础信息。具体返回的信息内容参考FrameNode中提供的接口。

查找获得FrameNode的方式包括三种:

  1. 使用getFrameNodeById获取。

  2. 使用getFrameNodeByUniqueId获取。

  3. 通过无感监听获取。

说明

当前接口提供的可查询的信息包括:

  • 节点大小:getMeasuredSize,getUserConfigSize

  • 布局信息:getPositionToWindow,getPositionToParent,getLayoutPosition,getUserConfigBorderWidth,getUserConfigPadding,getUserConfigMargin

  • 节点信息:getId,getUniqueId,getNodeType,getOpacity,isVisible,isClipToFrame,isAttached,getInspectorInfo,getCustomProperty

RenderNode

概述

对于不具备自己的渲染环境的三方框架,虽然实现了前端的解析以及布局、事件等处理,但需要依赖系统提供的基础渲染、动画的能力。FrameNode上的通用属性、通用事件对这一类框架是多余的,会进行多次冗余的操作,包括布局、事件等处理逻辑。

RenderNode是更加轻量级的渲染节点,仅包含渲染相关的能力。在该节点上暴露了设置基础的渲染属性的能力,并提供节点的动态增加、删除能力以及自定义绘制的能力。可以向三方框架提供基础的渲染、动画能力。

创建和删除节点

RenderNode提供了节点创建和删除的能力。可以通过RenderNode的构造函数创建自定义的RenderNode节点。通过构造函数创建的节点对应一个实体的节点。同时,可以通过RenderNode中的dispose接口来实现与实体节点的绑定关系的解除。

操作节点树

RenderNode提供了节点的增、删、查、改的能力,能够修改节点的子树结构;可以对所有RenderNode的节点的父子节点做出查询操作,并返回查询结果。

说明

  • RenderNode中查询获取得到的子树结构按照开发通过RenderNode的接口传递的参数构建。

  • RenderNode如果要与原生组件结合显示,使用需要依赖FrameNode中获取的RenderNode进行挂载上树。

设置和获取渲染相关属性

RenderNode中可以设置渲染相关的属性,包括:backgroundColor,clipToFrame,opacity,size,position,frame,pivot,scale,translation,rotation,transform,shadowColor,shadowOffset,shadowAlpha,shadowElevation,shadowRadius,borderStyle,borderWidth,borderColor,borderRadius,shapeMask,shapeClip,markNodeGroup等。

说明

  • RenderNode中查询获取得到的属性为设置的属性值。

  • 若未传入参数或者传入参数为非法值则查询获得的为默认值。

  • 不建议对BuilderNode中的RenderNode进行修改操作。

自定义绘制

通过重写RenderNode中的draw方法,可以自定义RenderNode的绘制内容,通过invalidate接口可以主动触发节点的重新绘制。

说明

  • 同时同步触发多个invalidate仅会触发一次重新绘制。

  • 自定义绘制有两种绘制方式:通过ArkTS接口进行调用和通过Node-API进行调用。

TypeScript 复制代码
import { FrameNode, NodeController, RenderNode } from '@kit.ArkUI';
import { drawing } from '@kit.ArkGraphics2D';

class MyRenderNode extends RenderNode {
  draw(context: DrawContext) {
    // 获取canvas对象
    const canvas = context.canvas;
    // 创建笔刷
    const brush = new drawing.Brush();
    // 设置笔刷颜色
    brush.setColor({ alpha: 255, red: 255, green: 0, blue: 0 });
    canvas.attachBrush(brush);
    // 绘制矩阵
    canvas.drawRect({ left: 0, right: 200, top: 0, bottom: 200 });
    canvas.detachBrush();
  }
}

const renderNode = new MyRenderNode();
renderNode.frame = { x: 0, y: 0, width: 300, height: 300 };
renderNode.backgroundColor = 0xff0000ff;
renderNode.opacity = 0.5;

class MyNodeController extends NodeController {
  private rootNode: FrameNode | null = null;

  makeNode(uiContext: UIContext): FrameNode | null {
    this.rootNode = new FrameNode(uiContext);

    const rootRenderNode = this.rootNode?.getRenderNode();
    if (rootRenderNode !== null) {
      rootRenderNode.frame = { x: 0, y: 0, width: 500, height: 500 }
      rootRenderNode.appendChild(renderNode);
    }

    return this.rootNode;
  }
}

@Entry
@Component
struct Index {
  private myNodeController: MyNodeController = new MyNodeController();

  build() {
    Column() {
      NodeContainer(this.myNodeController)
        .width('100%')
      Button('Invalidate')
        .onClick(() => {
          // 同步调用多次,仅触发一次重绘
          renderNode.invalidate();
          renderNode.invalidate();
        })
    }
  }
}

BuilderNode

概述

BuilderNode提供能够挂载原生组件的能力,支持通过无状态的UI方法全局@Builder生成组件树,并通过getFrameNode获取组件树的根FrameNode节点。该节点可以通过NodeController直接返回,挂载在NodeContainer节点下,也可以在FrameNode树结构和RenderNode树结构嵌入声明式的组件结构,实现混合显示的能力。同时BuilderNode可以提供纹理导出的功能,导出的纹理用于在XComponent中进行同层渲染显示。

BuilderNode创建的ArkTS原生控件树支持与自定义节点(例如:FrameNode、RenderNode)进行关联使用,实现了原生组件与自定义节点的混合显示。对于使用自定义节点的能力进行对接的三方框架,BuilderNode为其提供了嵌入原生组件的能力。

BuilderNode提供了组件预创建的能力,能够自定义原生组件的创建开始的时间,在后续的业务中动态挂载显示。对于一些在创建初始化耗时较长的声明式组件,比如WebXComponent等,预创建可以有效减少组件初始化的耗时。

BuilderNode仅可作为叶子节点进行使用。如有更新需要,建议通过BuilderNode中的Update方式触发更新,不建议通过BuilderNode中获取的RenderNode对节点进行修改操作。

说明

  • BuilderNode只支持一个由wrapBuilder包装的全局@Builder.

  • 一个新建的BuildNode在build之后才能通过getFrameNode获取到一个指向根节点的FrameNode对象,否则返回null。

  • 如果传入的Builder的根节点为语法节点(if/else/foreach/...),需要额外生成一个FrameNode,在节点树中的显示为"BuilderProxyNode"。

  • 如果BuilderNode通过getFrameNode将节点挂载在另一个FrameNode上,或者将其作为子节点挂载在NodeContainer节点上。则节点中使用父组件的布局约束进行布局。

  • 如果BuilderNode的FrameNode通过getRenderNode形式将自己的节点挂载在RenderNode节点上,由于其FrameNode未上树,其大小默认为0,需要通过构造函数中的selfIdeaSize显式指定布局约束大小,才能正常显示。

  • BuilderNode的预加载并不会减少组件的创建时间。Web组件创建的时候需要在内核中加载资源,预创建不能减少Web组件的创建的时间,但是可以让内核进行预加载,减少正式使用时候内核的加载耗时。

创建BuilderNode对象

BuilderNode对象为一个模板类,需要在创建的时候指定类型。该类型需要与后续build方法中传入的WrappedBuilder的类型保持一致,否则会存在编译告警导致编译失败。

创建原生组件树

通过BuilderNode的build可以实现原生组件树的创建。依照传入的WrappedBuilder对象创建组件树,并持有组件树的根节点。

说明

无状态的UI方法全局@Builder最多拥有一个根节点。

build方法中对应的@Builder支持一个参数作为入参。

build中对于@Builder嵌套@Builder进行使用的场景,需要保证嵌套的参数与build的中提供的入参一致。

对于@Builder嵌套@Builder进行使用的场景,如果入参类型不一致,则要求增加BuilderOptions字段作为build的入参。

更新原生组件树

通过BuilderNode对象的build创建原生组件树。依照传入的WrappedBuilder对象创建组件树,并持有组件树的根节点。自定义组件的更新遵循状态管理的更新机制。WrappedBuilder中直接使用的自定义组件其父组件为BuilderNode对象。因此,更新子组件即WrappedBuilder中定义的自定义组件,需要遵循状态管理的定义将相关的状态变量定义为@Prop或者@ObjectLink。装饰器的选择请参照状态管理的装饰器规格结合应用开发需求进行选择。

使用update更新BuilderNode中的节点。

使用updateConfiguration触发BuilderNode中节点的全量更新。

更新BuilderNode中的节点。

解除实体节点引用关系

由于BuilderNode对应的是后端的实体节点,正常的内存释放依赖前端对象的回收。如果期望直接释放后端的节点对象,则可以通过调用dispose与实体节点解除引用关系,此时持有的前端BuilderNode对象不再影响实体节点的生命周期。

说明

当BuilderNode对象调用dispose之后,不仅BuilderNode对象与后端实体节点解除引用关系,BuilderNode中的FrameNode与RenderNode也会同步和实体节点解除引用关系。

注入触摸事件

BuilderNode中提供了postTouchEvent,可以通过该接口向BuilderNode中绑定的组件注入触摸事件,实现事件的模拟转发。通过postTouchEvent向BuilderNode对应的节点树中注入触摸事件。向BuilderNode中的Column组件转发另一个Column的接收事件,即点击下方的Column组件,上方的Colum组件也会收到同样的触摸事件。当Button中的事件被成功识别的时候,返回值为true。

相关推荐
小曲曲26 分钟前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
学不会•2 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS2 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜4 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点4 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow4 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o4 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
Random_index4 小时前
#Uniapp篇:支持纯血鸿蒙&发布&适配&UIUI
uni-app·harmonyos
刚刚好ā5 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年6 小时前
react中useMemo的使用场景
前端·react.js·前端框架