- 目錄
一锰提、鴻蒙應(yīng)用開發(fā)-初體驗(yàn)
二鸡典、鴻蒙應(yīng)用開發(fā)-基礎(chǔ)組件
三、鴻蒙應(yīng)用開發(fā)-組件樣式
四榛丢、鴻蒙應(yīng)用開發(fā)-組件構(gòu)建函數(shù)
自定義構(gòu)建函數(shù)
1. 構(gòu)建函數(shù)-@Builder
ArkUI還提供了一種更輕量的UI元素復(fù)用機(jī)制 @Builder铲球,可以將重復(fù)使用的UI元素抽象成一個(gè)方法,在 build 方法里調(diào)用晰赞。
- 組件內(nèi)定義
- 全局定義
1)組件內(nèi)定義
@Builder MyBuilderFunction() {}
this.MyBuilderFunction()
2)全局定義
@Builder function MyGlobalBuilderFunction() {}
MyGlobalBuilderFunction()
?????? 練習(xí)案例→商品詳情-更多按鈕
1.png
@Entry
@Component
struct Index {
build() {
Column() {
GridRow({ columns: 2, gutter: 15 }) {
GridCol({ span: 2 }) {
Column() {
Row() {
Text('評價(jià)(2000+)')
.layoutWeight(1)
.fontWeight(600)
// TODO
}
.padding(10)
Row()
.height(100)
}
.borderRadius(12)
.backgroundColor('#fff')
}
GridCol() {
Column() {
Row() {
Text('推薦')
.layoutWeight(1)
.fontWeight(600)
// TODO
}
.padding(10)
Row()
.height(100)
}
.borderRadius(12)
.backgroundColor('#fff')
}
GridCol() {
Column() {
Row() {
Text('體驗(yàn)')
.layoutWeight(1)
.fontWeight(600)
// TODO
}
.padding(10)
Row()
.height(100)
}
.borderRadius(12)
.backgroundColor('#fff')
}
}
}
.height('100%')
.padding(15)
.backgroundColor('#f5f5f5')
}
}
使用 @Builder 提取UI結(jié)構(gòu)
@Entry
@Component
struct Index {
@Builder
MoreBuilder () {
Row() {
Text('查看更多')
.fontSize(14)
.fontColor('#666666')
Image($r('app.media.ic_public_arrow_right'))
.width(16)
.fillColor('#666666')
}
}
build() {
Column() {
GridRow({ columns: 2, gutter: 15 }) {
GridCol({ span: 2 }) {
Column() {
Row() {
Text('評價(jià)(2000+)')
.layoutWeight(1)
.fontWeight(600)
this.MoreBuilder()
}
.padding(10)
Row()
.height(100)
}
.borderRadius(12)
.backgroundColor('#fff')
}
GridCol() {
Column() {
Row() {
Text('推薦')
.layoutWeight(1)
.fontWeight(600)
this.MoreBuilder()
}
.padding(10)
Row()
.height(100)
}
.borderRadius(12)
.backgroundColor('#fff')
}
GridCol() {
Column() {
Row() {
Text('體驗(yàn)')
.layoutWeight(1)
.fontWeight(600)
this.MoreBuilder()
}
.padding(10)
Row()
.height(100)
}
.borderRadius(12)
.backgroundColor('#fff')
}
}
}
.height('100%')
.padding(15)
.backgroundColor('#f5f5f5')
}
}
小結(jié):
遇到非遍歷情況下稼病,一個(gè)組件分散著相同的UI結(jié)構(gòu),可以使用 @Builder 更輕量
其他:GridRow GridCol 柵格布局
2. 構(gòu)建函數(shù)-傳參傳遞
1)按值傳遞(場景:構(gòu)建不同的UI)
@Builder MyBuilderFunction( title: string ) {}
this.MyBuilderFunction('Title')
需求:不同板塊查看更多文案不一樣
評價(jià) 好評率 98%
推薦 查看全部
-
體驗(yàn) 4 條測評
2.png
@Builder
MoreBuilder (title: string) {
Row() {
Text(title)
.fontSize(14)
.fontColor('#666666')
Image($r('app.media.ic_public_arrow_right'))
.width(16)
.fillColor('#666666')
}
}
this.MoreBuilder('好評率 98%')
this.MoreBuilder('查看全部')
this.MoreBuilder('4 條測評')
2)引用傳遞(場景:當(dāng)傳遞的數(shù)據(jù)更新掖鱼,需要更新UI)
需求:
- 點(diǎn)擊按鈕后模擬加載好評率數(shù)據(jù)
3.png
@Entry
@Component
struct Index {
@State
rate: number = 0
@Builder
MoreBuilder(params: { title: string }) {
Row() {
Text(params.title)
.fontSize(14)
.fontColor('#666666')
Image($r('app.media.ic_public_arrow_right'))
.width(16)
.fillColor('#666666')
}
}
build() {
Column() {
Button('獲取數(shù)據(jù)')
.margin({ bottom: 15 })
.onClick(() => {
this.rate = 99
})
GridRow({ columns: 2, gutter: 15 }) {
GridCol({ span: 2 }) {
Column() {
Row() {
Text('評價(jià)(2000+)')
.layoutWeight(1)
.fontWeight(600)
this.MoreBuilder({ title: `好評率 ${this.rate} %` })
}
.padding(10)
Row()
.height(100)
}
.borderRadius(12)
.backgroundColor('#fff')
}
GridCol() {
Column() {
Row() {
Text('推薦')
.layoutWeight(1)
.fontWeight(600)
this.MoreBuilder({ title: '查看全部' })
}
.padding(10)
Row()
.height(100)
}
.borderRadius(12)
.backgroundColor('#fff')
}
GridCol() {
Column() {
Row() {
Text('體驗(yàn)')
.layoutWeight(1)
.fontWeight(600)
this.MoreBuilder({ title: '4 條測評' })
}
.padding(10)
Row()
.height(100)
}
.borderRadius(12)
.backgroundColor('#fff')
}
}
}
.height('100%')
.padding(15)
.backgroundColor('#f5f5f5')
}
}
- 使用** @Builder** 復(fù)用邏輯的時(shí)候然走,支持傳參可以更靈活的渲染UI
- 參數(shù)可以使用狀態(tài)數(shù)據(jù),不過建議通過對象的方式傳入 @Builder
- 構(gòu)建函數(shù)-@BuilderParam 傳遞UI
@BuilderParam 該裝飾器用于聲明任意UI描述的一個(gè)元素戏挡,類似 slot 占位符
前置知識
組件屬性初始化:
- 定義組件聲明屬性 title: string
- 使用組件初始化屬性 Comp({ title: string })
-
尾隨閉包初始化組件
- 組件內(nèi)有且僅有一個(gè)使用 @BuilderParam 裝飾的屬性
-
參數(shù)初始化組件
- 組件內(nèi)有多個(gè)使用 @BuilderParam 裝飾器屬性
1)尾隨閉包初始化組件(默認(rèn)插槽)
需求:
- 標(biāo)題文字和更多文案通過屬性傳入
-
內(nèi)容結(jié)構(gòu)需要傳入
4.png
@Component
struct PanelComp {
title: string
more: string
@BuilderParam
panelContent: () => void = this.DefaultPanelContent
// 備用 Builder
@Builder
DefaultPanelContent () {
Text('默認(rèn)內(nèi)容')
}
build() {
Column() {
Row() {
Text(this.title)
.layoutWeight(1)
.fontWeight(600)
Row() {
Text(this.more)
.fontSize(14)
.fontColor('#666666')
Image($r('app.media.ic_public_arrow_right'))
.width(16)
.fillColor('#666666')
}
}
.padding(10)
Row() {
this.panelContent()
}
.height(100)
}
.borderRadius(12)
.backgroundColor('#fff')
}
}
@Entry
@Component
struct Index {
build() {
Column() {
GridRow({ columns: 2, gutter: 15 }) {
GridCol({ span: 2 }) {
PanelComp({ title: '評價(jià)(2000+)', more: '好評率98%' })
}
GridCol() {
PanelComp({ title: '推薦', more: '查看全部' }){
Text('推薦內(nèi)容')
}
}
GridCol() {
PanelComp({ title: '體驗(yàn)', more: '4 條測評' }){
Text('體驗(yàn)內(nèi)容')
}
}
}
}
.height('100%')
.padding(15)
.backgroundColor('#f5f5f5')
}
}
2)參數(shù)初始化組件(具名插槽)
需求:需要傳入內(nèi)容結(jié)構(gòu)和底部結(jié)構(gòu)
6.png
@Component
struct PanelComp {
title: string
more: string
@BuilderParam
panelContent: () => void
@BuilderParam
panelFooter: () => void
build() {
Column() {
Row() {
Text(this.title)
.layoutWeight(1)
.fontWeight(600)
Row() {
Text(this.more)
.fontSize(14)
.fontColor('#666666')
Image($r('app.media.ic_public_arrow_right'))
.width(16)
.fillColor('#666666')
}
}
.padding(10)
Row() {
this.panelContent()
}
.height(100)
Row() {
this.panelFooter()
}
.height(50)
}
.borderRadius(12)
.backgroundColor('#fff')
}
}
@Entry
@Component
struct Index {
@Builder
ContentBuilderA() {
Text('評價(jià)內(nèi)容')
}
@Builder
FooterBuilderA() {
Text('評價(jià)底部')
}
build() {
Column() {
GridRow({ columns: 2, gutter: 15 }) {
GridCol({ span: 2 }) {
PanelComp({
title: '評價(jià)(2000+)',
more: '好評率98%',
panelFooter: this.FooterBuilderA,
panelContent: this.ContentBuilderA
})
}
// GridCol() {
// PanelComp({ title: '推薦', more: '查看全部' }){
// Text('推薦內(nèi)容')
// }
// }
//
// GridCol() {
// PanelComp({ title: '體驗(yàn)', more: '4 條測評' }){
// Text('體驗(yàn)內(nèi)容')
// }
// }
}
}
.height('100%')
.padding(15)
.backgroundColor('#f5f5f5')
}
}
- 當(dāng)子組件使用一個(gè) @BuilderParam 的時(shí)候芍瑞,使用組件的時(shí)候在尾隨 {} 插入U(xiǎn)I結(jié)構(gòu)
- 當(dāng)子組件使用多個(gè) @BuilderParam 的時(shí)候,使用組件的時(shí)候 Comp({ xxx: this.builderFn }) 傳入
- 子組件本身可以提供一個(gè)默認(rèn)的 @Builder 函數(shù)作為 @BuilderParam 備用函數(shù)褐墅,當(dāng)做備用內(nèi)容使用
4. 構(gòu)建函數(shù)-系統(tǒng)組件自定義UI
在一些系統(tǒng)組件中拆檬,根據(jù)配置無法達(dá)到預(yù)期UI,可以使用 @Builder 構(gòu)建函數(shù)自定義UI妥凳,前提該組件支持自定義竟贯。
在一些系統(tǒng)組件中,根據(jù)配置無法達(dá)到預(yù)期UI逝钥,可以使用 @Builder 構(gòu)建函數(shù)自定義UI屑那,前提該組件支持自定義。
7.jpeg
需求:自定義 Tabs 組件的 TabBar UI結(jié)構(gòu)
class ToolBarItem {
defaultIcon: string | Resource
activeIcon: string | Resource
label: string
}
@Entry
@Component
struct Index {
@State
activeIndex: number = 0
toolBars: ToolBarItem[] = [
{ defaultIcon: $r('app.media.home'), activeIcon: $r('app.media.home_select'), label: '首頁' },
{ defaultIcon: $r('app.media.project'), activeIcon: $r('app.media.project_select'), label: '項(xiàng)目' },
{ defaultIcon: $r('app.media.interview'), activeIcon: $r('app.media.interview_select'), label: '面經(jīng)' },
{ defaultIcon: $r('app.media.mine'), activeIcon: $r('app.media.mine_select'), label: '我的' }
]
@Builder
TabBarBuilder(item: ToolBarItem, index: number) {
Column() {
Image(this.activeIndex === index ? item.activeIcon : item.defaultIcon)
.width(24)
Text(item.label)
.fontSize(12)
.margin({ top: 4 })
.lineHeight(12)
.fontColor(this.activeIndex === index ? '#000' : '#aaa')
}
}
build() {
Tabs({
index: this.activeIndex
}) {
ForEach(this.toolBars, (item: ToolBarItem, index: number) => {
TabContent() {
Text(index.toString())
}
.tabBar(this.TabBarBuilder(item, index))
})
}
.barPosition(BarPosition.End)
.onChange(index => this.activeIndex = index)
}
}