
文章目录前言一、Builder 是什么二、Builder vs Component三、项目中的三个 Builder3.1 titleBuilder标题栏3.2 bindBuilder底部弹窗内容3.3 stationInfoCard加油站卡片带参数四、全局 Builder五、Builder 的限制5.1 不能有独立的 State5.2 参数传递限制六、什么时候用 Builder什么时候用 Component七、实际建议如何拆分复杂页面总结前言打开GasStationPage.ets你会发现有三个Builder装饰的方法stationInfoCard、bindBuilder、titleBuilder。这些方法都返回 UI但又不是独立的Component组件。Builder到底是什么和组件有什么区别什么时候用Builder什么时候用Component这篇文章讲清楚这些问题。项目预览一、Builder 是什么Builder是一个轻量级的 UI 复用机制可以把一段 UI 代码抽取成一个可调用的 UI 片段。EntryComponentstruct MyPage{// 定义 Builder把一段 UI 抽取出来BuilderheaderBuilder(){Row(){Text(标题).fontSize(20).fontWeight(700)}.width(100%).height(50)}build(){Column(){this.headerBuilder()// 调用 Builder就像调用函数一样// 其他内容...}}}二、Builder vs Component特性BuilderComponent定义方式函数方法结构体struct状态管理共享父组件的状态独立的状态作用域参数传递直接函数参数通过 Prop/Link 等生命周期无独立生命周期有完整生命周期复用粒度UI 片段轻量独立组件重量适用场景复杂页面内部拆分跨页面复用的独立组件核心区别Builder里的 UI 是父组件的一部分共享父组件的this即可以直接访问父组件的状态变量Component是独立的组件有自己的状态作用域。三、项目中的三个 Builder3.1 titleBuilder标题栏BuildertitleBuilder(){Row({space:Constants.SPACE_8}){Image($r(app.media.back)).width(Constants.IMAGE_BACK_WIDTH)// 40.height(Constants.IMAGE_BACK_HEIGHT)// 40.onClick((){this.pageInfos.pop();// 直接访问父组件的 pageInfos});Text($r(app.string.car_life)).fontWeight(Constants.FONT_WEIGHT_700).fontSize(Constants.FONT_SIZE_20).lineHeight(Constants.LINE_HEIGHT_27).fontColor($r(app.color.gas_station_name_color));}.width(Constants.FULL_PERCENT).padding({left:Constants.PADDING_RIGHT_16}).position({top:Constants.POSITION_TOP});}注意this.pageInfos.pop()——Builder里直接访问父组件GasStationPage的pageInfos这是Component做不到的子组件需要通过Prop/Link接收数据。为什么用 Builder 而不是 Component因为标题栏只在这一个页面用而且需要直接访问页面的路由栈pageInfos用Builder是最简单的方式。3.2 bindBuilder底部弹窗内容BuilderbindBuilder(){Column(){Scroll(){if(this.stationInfoListthis.stationInfoList.length0){List(){ForEach(this.stationInfoList,(station:StationData){// 直接用 stationInfoListListItem(){Row({space:Constants.SPACE_12}){this.stationInfoCard(station);// 调用另一个 Builder}.width(Constants.FULL_PERCENT);};},(station:StationData){returnstation.idstation.name;});}.width(Constants.FULL_PERCENT);}}// ...样式}.height(Constants.MY_BUILDER_COLUMN_HEIGHT);}Builder里可以调用另一个 Builderthis.stationInfoCard(station)就是在bindBuilder里调用了stationInfoCard。3.3 stationInfoCard加油站卡片带参数BuilderstationInfoCard(gasStation:StationData):void{// 注意有参数Column({space:Constants.SPACE_12}){// 卡片内容....onClick((){if(gasStation){this.openOrCloseMap(true);// 访问父组件方法this.moveToGasStation(gasStation.latitude,gasStation.longitude);// 访问父组件方法}else{this.getUIContext().getPromptAction().showToast({message:$r(app.string.Stay_tuned)});}});}}Builder可以有参数stationInfoCard接收一个StationData参数每次调用传入不同的数据渲染不同的卡片。调用时this.stationInfoCard(station)// 传入当前循环的加油站数据四、全局 Builder上面三个都是组件内部的局部 Builder作为组件的方法。Builder也可以定义在组件外部成为全局 Builder// 文件顶层定义全局BuilderexportfunctionGasStationPageBuilder(){GasStationPage();}// 可以在任何地方调用GasStationPageBuilder();为什么GasStationPageBuilder是全局 Builder因为它是 Navigation 路由系统的入口。route_map.json里配置了buildFunction: GasStationPageBuilder框架需要通过这个全局函数来创建页面所以必须是全局可访问的export function。全局Builder和组件方法的区别全局不属于任何组件没有this不能访问组件状态局部组件方法属于组件有this可以访问组件的属性和方法五、Builder 的限制5.1 不能有独立的 StateBuildermyBuilder(){Statecount:number0;// ❌ 报错Builder 里不能定义 StateText(${count})}Builder不能定义自己的状态变量。如果需要状态要么用父组件的状态变量共享状态把 UI 抽成真正的Component5.2 参数传递限制// 简单类型参数按值传递父组件状态变化不会同步到 Builder 里BuildermyBuilder(text:string){Text(text)// text 变化不会自动刷新除非父组件重新调用}// 对象类型参数传引用可以观察到变化BuildermyBuilder(config:{text:string}){Text(config.text)// config 对象里的属性变化可以被观察到}提示如果Builder里的 UI 需要响应父组件某个值的变化建议直接用this.xxx访问父组件的State变量而不是通过参数传递。六、什么时候用 Builder什么时候用 Component用 Builder 当UI 片段只在当前组件内使用需要直接访问父组件的状态变量UI 片段不需要独立的状态和生命周期只是为了让代码更整洁拆分大build()函数用 Component 当UI 组件需要在多个页面复用组件需要独立的状态管理组件有复杂的生命周期aboutToAppear、onWillDisappear等组件需要接受外部的数据绑定Prop、Link、ObjectLink七、实际建议如何拆分复杂页面面对一个复杂页面推荐这样的拆分策略GasStationPageComponent Entry ├── titleBuilderBuilder ← 只此页面用需要访问页面路由 ├── bindBuilderBuilder ← 只此页面用需要访问页面数据 │ └── stationInfoCardBuilder ← 复杂卡片提取为 Builder如果stationInfoCard未来需要在其他地方复用就把它抽成独立的Component// StationCard.etsComponentstruct StationCard{PropgasStation:StationData;onClickCallback:(station:StationData)void(){};build(){// 卡片 UI}}总结Builder是 ArkUI 中轻量的 UI 复用机制局部 Builder组件方法共享父组件状态可有参数适合拆分同一页面的 UI 片段全局 Builder文件顶层函数无this适合路由入口等全局调用场景vs ComponentBuilder 轻量但功能有限Component 独立但较重GasStationPage用三个 Builder 把复杂的build()方法拆分成几个有意义的部分代码可读性大大提升。下一篇讲LocationKit 定位服务——geoLocationManager是怎么获取用户位置的异步获取位置有哪些注意事项。