前提:基于官網3.1/4.0文檔。參考官網文檔
基于Android開發體系來進行比較和思考。(或有偏頗,自行斟酌)
1.概念
ArkUI通過自定義組件的build()函數和@builder裝飾器中的聲明式UI描述語句構建相應的UI。在聲明式描述語句中開發者除了使用系統組件外,還可以使用渲染控制語句來輔助UI的構建,這些渲染控制語句包括控制組件是否顯示的條件渲染語句,基于數組數據快速生成組件的循環渲染語句以及針對大數據量場景的數據懶加載語句。
2.用法
1.if else
@Component
struct CounterView {@State counter: number = 0;label: string = 'unknown';build() {Row() {Text(`${this.label}`)Button(`counter ${this.counter} +1`).onClick(() => {this.counter += 1;})}}
}@Entry
@Component
struct MainView {@State toggle: boolean = true;build() {Column() {if (this.toggle) {CounterView({ label: 'CounterView #positive' })} else {CounterView({ label: 'CounterView #negative' })}Button(`toggle ${this.toggle}`).onClick(() => {this.toggle = !this.toggle;})}}
}
簡單的案例,只有滿足判斷條件才渲染。
2.ForEach:循環渲染
ForEach(arr: Array,itemGenerator: (item: any, index?: number) => void,keyGenerator?: (item: any, index?: number) => string
)
以上是經典結構。
itemGenerator 對應回調實現Item(也就是ViewHolder)
keyGenerator對應列表的key id,以此來區分item的刷新渲染。(同樣的id認為是同一個item)
@Entry
@Component
struct ArticleListView {@State isListReachEnd: boolean = false;@State articleList: Array<Article> = [new Article('001', '第1篇文章', '文章簡介內容'),new Article('002', '第2篇文章', '文章簡介內容'),new Article('003', '第3篇文章', '文章簡介內容'),new Article('004', '第4篇文章', '文章簡介內容'),new Article('005', '第5篇文章', '文章簡介內容'),new Article('006', '第6篇文章', '文章簡介內容')]loadMoreArticles() {this.articleList.push(new Article('007', '加載的新文章', '文章簡介內容'));}build() {Column({ space: 5 }) {List() {ForEach(this.articleList, (item: Article) => {ListItem() {ArticleCard({ article: item }).margin({ top: 20 })}}, (item: Article) => item.id)}.onReachEnd(() => {this.isListReachEnd = true;}).parallelGesture(PanGesture({ direction: PanDirection.Up, distance: 80 }).onActionStart(() => {if (this.isListReachEnd) {this.loadMoreArticles();this.isListReachEnd = false;}})).padding(20).scrollBar(BarState.Off)}.width('100%').height('100%').backgroundColor(0xF1F3F5)}
}@Component
struct ArticleCard {@Prop article: Article;build() {Row() {Image($r('app.media.icon')).width(80).height(80).margin({ right: 20 })Column() {Text(this.article.title).fontSize(20).margin({ bottom: 8 })Text(this.article.brief).fontSize(16).fontColor(Color.Gray).margin({ bottom: 8 })}.alignItems(HorizontalAlign.Start).width('80%').height('100%')}.padding(20).borderRadius(12).backgroundColor('#FFECECEC').height(120).width('100%').justifyContent(FlexAlign.SpaceBetween)}
}
代碼很好懂,也和RecycleView類似,通過改變數據源來進行頁面UI渲染。
3.LazyForEach:數據懶加載
class BasicDataSource implements IDataSource {private listeners: DataChangeListener[] = [];private originDataArray: string[] = [];public totalCount(): number {return 0;}public getData(index: number): string {return this.originDataArray[index];}registerDataChangeListener(listener: DataChangeListener): void {if (this.listeners.indexOf(listener) < 0) {console.info('add listener');this.listeners.push(listener);}}unregisterDataChangeListener(listener: DataChangeListener): void {const pos = this.listeners.indexOf(listener);if (pos >= 0) {console.info('remove listener');this.listeners.splice(pos, 1);}}notifyDataReload(): void {this.listeners.forEach(listener => {listener.onDataReloaded();})}notifyDataAdd(index: number): void {this.listeners.forEach(listener => {listener.onDataAdd(index);})}notifyDataChange(index: number): void {this.listeners.forEach(listener => {listener.onDataChange(index);})}notifyDataDelete(index: number): void {this.listeners.forEach(listener => {listener.onDataDelete(index);})}
}class MyDataSource extends BasicDataSource {private dataArray: string[] = [];public totalCount(): number {return this.dataArray.length;}public getData(index: number): string {return this.dataArray[index];}public addData(index: number, data: string): void {this.dataArray.splice(index, 0, data);this.notifyDataAdd(index);}public pushData(data: string): void {this.dataArray.push(data);this.notifyDataAdd(this.dataArray.length - 1);}
}@Entry
@Component
struct MyComponent {private data: MyDataSource = new MyDataSource();aboutToAppear() {for (let i = 0; i <= 20; i++) {this.data.pushData(`Hello ${i}`)}}build() {List({ space: 3 }) {LazyForEach(this.data, (item: string) => {ListItem() {Row() {Text(item).fontSize(50).onAppear(() => {console.info("appear:" + item)})}.margin({ left: 10, right: 10 })}.onClick(() => {// 點擊追加子組件this.data.pushData(`Hello ${this.data.totalCount()}`);})}, (item: string) => item)}.cachedCount(5)}
}
上述增加數據item的簡單示例。也并沒有什么特別,無非是一些固定方法的回調來獲取列表的基本數據。
3.結論
至此入門篇章完畢,官網關于渲染控制這塊就說了這幾個小點,其實這是非常淺層次的內容,應該說它只涉及了應用,而且只是幾個簡單應用方面。關于底層實現及更復雜方面的應用太少。這些看看在后續的學習中是否有涉及。