<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      鴻蒙應用開發從入門到實戰(十八):組件編程思想之代碼復用

      大家好,我是潘Sir,持續分享IT技術,幫你少走彎路。《鴻蒙應用開發從入門到項目實戰》系列文章持續更新中,陸續更新AI+編程、企業級項目實戰等原創內容、歡迎關注!

      ArkUI提供了豐富的系統組件,用于制作鴻蒙原生應用APP的UI,在制作UI時會經常遇到代碼或樣式重復問題,本文通過ArkUI提供的適配器實現代碼復用。

      一、樣式復用

      1.1 概述

      當多個組件具有相同的樣式時,若每個組件都單獨設置,將會有大量的重復代碼。為避免重復代碼,開發者可使用@Styles或者@Extend裝飾器將多條樣式設置提煉成一個方法,然后直接在各組件聲明的位置進行調用,這樣就能完成樣式的復用。
      1按鈕復用

      1.2 @Styles方法

      @Styles方法可定義在組件內或者全局,具體語法如下

      • 組件內
      @Entry
      @Component
      struct StylesPage {
        build() {
          Column() {
            Row({ space: 50 }) {
              Button('確認')
                .type(ButtonType.Normal)
                .backgroundColor(Color.Green)
                .compButtonStyle() //復用樣式
                .onClick(() => console.log('確認'))
              Button('取消')
                .type(ButtonType.Normal)
                .backgroundColor(Color.Gray)
                .compButtonStyle() //復用樣式
                .onClick(() => console.log('取消'))
            }
          }.width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)
        }
      
        //組件內樣式定義
        @Styles compButtonStyle() {
          .width(100)
          .height(40)
          .borderRadius(10)
        }
      }
      
      • 全局
      @Entry
      @Component
      struct StylesPage {
        build() {
          Column() {
            Row({ space: 50 }) {
              Button('確認')
                .type(ButtonType.Normal)
                .backgroundColor(Color.Green)
                .globalButtonStyle() //復用樣式
                .onClick(() => console.log('確認'))
              Button('取消')
                .type(ButtonType.Normal)
                .backgroundColor(Color.Gray)
                .globalButtonStyle() //復用樣式
                .onClick(() => console.log('取消'))
            }
          }.width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)
        }
      }
      
      //全局樣式定義
      @Styles function globalButtonStyle() {
        .width(100)
        .height(40)
        .borderRadius(10)
      }
      

      注意

      1. 組件內@Styles方法只能在當前組件中使用,全局@Styles方法目前只允許在當前的.ets文件中使用
      2. 組件內定義@Styles方法時不需要使用function關鍵字,全局的@Styles方法需要使用function關鍵字
      3. @Styles方法中只能包含通用屬性方法通用事件方法
      4. @Styles方法不支持參數

      示例代碼

      pages/component目錄下新建resue目錄,新建StylesPage.ets文件

      @Entry
      @Component
      struct StylesPage {
        build() {
          Column() {
            Row({ space: 50 }) {
              Button('確認')
                .type(ButtonType.Normal)
                .backgroundColor(Color.Green)
                .compButtonStyle() //復用樣式
                  // .globalButtonStyle() //復用樣式
                .onClick(() => console.log('確認'))
              Button('取消')
                .type(ButtonType.Normal)
                .backgroundColor(Color.Gray)
                .compButtonStyle() //復用樣式
                  // .globalButtonStyle() //復用樣式
                .onClick(() => console.log('取消'))
            }
          }.width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)
        }
      
        //組件內樣式定義
        @Styles compButtonStyle() {
          .width(100)
          .height(40)
          .borderRadius(10)
        }
      }
      
      //全局樣式定義
      @Styles function globalButtonStyle() {
        .width(100)
        .height(40)
        .borderRadius(10)
      }
      

      1.3 @Extend方法

      @Extend裝飾的方法同樣可用于組件樣式的復用,與@Styles不同的是,@Extend方法只能定義在全局。并且@Extend方法只能用于指定類型的組件,例如以下方法只能用于Button組件(可以理解為是Button組件的擴展樣式)

      @Extend(Button) function buttonStyle(){
        ...
      }
      

      由于@Extend方法只能用于指定類型的組件,因此方法中可包含指定組件的專有屬性方法專有事件方法。另外,@Extend方法還支持參數,具體語法如下

      @Entry
      @Component
      struct ExtendPage {
        build() {
          Column() {
            Row({ space: 50 }) {
              Button('確認')
                .buttonExtendStyle(Color.Green, () => console.log('確認')) //復用樣式
              Button('取消')
                .buttonExtendStyle(Color.Gray, () => console.log('取消')) //復用樣式
            }
          }.width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)
        }
      }
      
      //樣式定義
      @Extend(Button) function buttonExtendStyle(color: Color, callback: () => void) {
        .width(100)
        .height(40)
        .borderRadius(10)
        .type(ButtonType.Normal)
        .backgroundColor(color)
        .onClick(callback)
      }
      

      總結

      1. @Extend方法只能定義在全局,使用范圍目前只限于當前的.ets文件
      2. @Extend方法用于特定類型的組件,因此可包含該組件的專有屬性方法專有事件方法
      3. @Extend方法支持參數

      示例代碼

      pages/component/resue目錄下新建ExtendPage.ets文件

      @Entry
      @Component
      struct ExtendPage {
        build() {
          Column() {
            Row({ space: 50 }) {
              Button('確認')
                .buttonExtendStyle(Color.Green, () => console.log('確認')) //復用樣式
              Button('取消')
                .buttonExtendStyle(Color.Gray, () => console.log('取消')) //復用樣式
            }
          }.width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)
        }
      }
      
      //樣式定義
      @Extend(Button) function buttonExtendStyle(color: Color, callback: () => void) {
        .width(100)
        .height(40)
        .borderRadius(10)
        .type(ButtonType.Normal)
        .backgroundColor(color)
        .onClick(callback)
      }
      

      二、UI結構復用

      2.1 概述

      當頁面有多個相同的UI結構時,若每個都單獨聲明,同樣會有大量重復的代碼。為避免重復代碼,可以將相同的UI結構提煉為一個自定義組件,完成UI結構的復用。

      除此之外,ArkTS還提供了一種更輕量的UI結構復用機制@Builder方法,開發者可以將重復使用的UI元素抽象成一個@Builder方法,該方法可在build()方法中調用多次,以完成UI結構的復用。

      2ui結構復用

      2.2 語法說明

      @Builder方法同樣可以定義在組件內或者全局,具體語法如下

      • 組件內
      @Entry
      @Component
      struct BuilderPage {
        build() {
          Column() {
            Row({ space: 50 }) {
              //復用UI結構
              this.compButtonBuilder($r('app.media.icon_edit'), '編輯', () => console.log('編輯'))
              this.compButtonBuilder($r('app.media.icon_send'), '發送', () => console.log('發送'))
            }
          }.width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)
        }
      
        //定義UI結構
        @Builder compButtonBuilder(icon: Resource, text: string, callback: () => void) {
          Button() {
            Row({ space: 10 }) {
              Image(icon)
                .width(25)
                .height(25)
              Text(text)
                .fontColor(Color.White)
                .fontSize(25)
            }
          }.width(120)
          .height(50)
          .onClick(callback)
        }
      }
      
      • 全局
      @Entry
      @Component
      struct BuilderPage {
        build() {
          Column() {
            Row({ space: 50 }) {
              //復用UI結構
              globalButtonBuilder($r('app.media.icon_edit'), '編輯', () => console.log('編輯'))
              globalButtonBuilder($r('app.media.icon_send'), '發送', () => console.log('發送'))
            }
          }.width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)
        }
      }
      
      //定義UI結構
      @Builder function globalButtonBuilder(icon: Resource, text: string, callback: () => void) {
          Button() {
            Row({ space: 10 }) {
              Image(icon)
                .width(25)
                .height(25)
              Text(text)
                .fontColor(Color.White)
                .fontSize(25)
            }
          }.width(120)
          .height(50)
          .onClick(callback)
      }
      

      注意

      1. 組件內@Builder方法可通過this訪問當前組件的屬性和方法,而全局@Builder方法則不能
      2. 組件內@Builder方法只能用于當前組件,全局@Builder方法導出(export)后,可用于整個應用。

      示例代碼

      拷貝icon_edit.png和icon_send.png文件到resources/base/media目錄

      pages/component/resue目錄下新建BuilderPage.ets文件

      @Entry
      @Component
      struct BuilderPage {
        build() {
          Column() {
            Row({ space: 50 }) {
              this.compButtonBuilder($r('app.media.icon_edit'), '編輯', () => console.log('編輯'))
              this.compButtonBuilder($r('app.media.icon_send'), '發送', () => console.log('發送'))
      
              // globalButtonBuilder($r('app.media.icon_edit'), '編輯', () => console.log('編輯'))
              // globalButtonBuilder($r('app.media.icon_send'), '發送', () => console.log('發送'))
            }
          }.width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)
        }
      
        @Builder compButtonBuilder(icon: Resource, text: string, callback: () => void) {
          Button() {
            Row({ space: 10 }) {
              Image(icon)
                .width(25)
                .height(25)
              Text(text)
                .fontColor(Color.White)
                .fontSize(25)
            }
          }.width(120)
          .height(50)
          .onClick(callback)
        }
      }
      
      
      @Builder function globalButtonBuilder(icon: Resource, text: string, callback: () => void) {
        Button() {
          Row({ space: 10 }) {
            Image(icon)
              .width(25)
              .height(25)
            Text(text)
              .fontColor(Color.White)
              .fontSize(25)
          }
        }.width(120)
        .height(50)
        .onClick(callback)
      }
      

      2.3 @Builder方法參數傳遞規則

      @Builder方法具有兩種參數傳遞機制——按值傳遞按引用傳遞。當只有一個參數且參數為對象字面量時為按引用傳遞,其余情況均為按值傳遞。

      按引用傳遞時,若傳遞的參數為狀態變量,則狀態變量的變化將會觸發@Builder方法內部UI的刷新;按值傳遞時則不會。

      示例代碼

      pages/component/resue目錄下新建BuilderParameterPage.ets文件

      @Entry
      @Component
      struct BuilderParameterPage {
        @State count: number = 0;
      
        build() {
          Column({ space: 50 }) {
            //按值傳遞
            valueTextBuilder(this.count)
            //按引用傳遞
            referenceTextBuilder({ count: this.count })
            Row({ space: 50 }) {
              Button('-1').onClick(() => {
                this.count--;
              })
              Button('+1').onClick(() => {
                this.count++;
              })
            }
          }.width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)
        }
      }
      
      @Builder function valueTextBuilder(count: number) {
        Text(`按值傳遞: ${count}`)
          .fontSize(30)
          .fontWeight(FontWeight.Bold)
      }
      
      @Builder function referenceTextBuilder(obj: { count: number }) {
        Text(`按引用傳遞: ${obj.count}`)
          .fontSize(30)
          .fontWeight(FontWeight.Bold)
      }
      

      2.4 @Builder方法和自定義組件的區別

      @Builder方法和自定義組件雖然都可以實現UI復用的效果,但是兩者還是有著本質的區別的,其中最為顯著的一個區別就是自定義組件可以定義自己的狀態變量,而@Builder方法則不能。

      以下案例中,每個待辦事項的UI結構都相同,因此可考慮將其提煉為一個自定義組件或者@Builder方法,但是由于每個待辦事項均有已完成未完成兩種狀態,因此需要為每個待辦事項都定義一個狀態變量,所以此時就只能使用自定義組件而不能使用@Builder方法。

      3todo

      總結

      若復用的UI結構沒有狀態,推薦使用@Builder方法,否則使用自定義組件。

      示例代碼

      pages/component/resue目錄下新建DifferencePage.ets文件

      @Entry
      @Component
      struct DifferencePage {
        build() {
          Column({ space: 10 }) {
            Text('待辦事項')
              .fontSize(30)
              .fontWeight(FontWeight.Bold)
              .width('100%')
            TodoItem({ text: '讀書' })
            TodoItem({ text: '運動' })
            TodoItem({ text: '早睡' })
          }
          .width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Start)
          .padding(10)
          .backgroundColor('#f2f2f2')
        }
      }
      
      @Component
      struct TodoItem {
        text: string;
        @State isDone: boolean = false;
      
        build() {
          Row() {
            Text(this.text)
              .fontSize(30)
              .fontWeight(FontWeight.Medium)
                //文本裝飾線,根據isDone的值選擇不同的類型
              .decoration({ type: this.isDone ? TextDecorationType.LineThrough : TextDecorationType.None })
      
            //用于填充Column/Row容器的剩余空間
            Blank()
      
            Toggle({ type: ToggleType.Checkbox })
              .onChange((value) => {
                this.isDone = value;
              })
          }
          .width('100%')
          .height(60)
          .backgroundColor(Color.White)
          .padding(10)
          .borderRadius(10)
        }
      }
      

      2.5 @BuilderParam

      @BuilderParam用于裝飾自定義組件(struct)中的屬性,其裝飾的屬性可作為一個UI結構的占位符,待創建該組件時,可通過參數為其傳入具體的內容。(其作用類似于Vue框架中的slot)。

      • 組件定義
      @Component
      struct Container {
         //@BuilderParam屬性
        @BuilderParam content: () => void
      
        build() {
          Column() {
            Text('其他內容') //其他內容
            this.content(); //占位符
            Button('其他內容') //其他內容
          }
        }
      }
      
      • UI結構定義
      @Builder function contentBuilder1() {
        ...
      }
      
      @Builder function contentBuilder2() {
        ...
      }
      
      @Builder function contentBuilder3() {
        ...
      }
      
      • 組件創建
      Container({ content: contentBuilder1 })
      
      Container({ content: contentBuilder2 })
      
      Container({ content: contentBuilder3 })
      

      下面通過一個案例展示@BuilderParam的具體用法,例如,現需要實現一個通用的卡片組件,如下圖所示

      4通用卡片效果

      卡片中顯示的內容不固定,例如

      5卡片內容不固定

      具體實現步驟如下:

      (1)卡片組件定義

      @Component
      struct Card {
        @BuilderParam content: () => void; //@BuilderParam屬性
      
        build() {
          Column() {
            this.content(); //占位符
          }.width('90%')
          .padding(10)
          .borderRadius(10)
          .shadow({ radius: 20 })
        }
      }
      

      效果

      4通用卡片效果

      (2)卡片內容定義

      @Builder function imageBuilder() {
        Column({ space: 10 }) {
          Image($r('app.media.img_harmony'))
            .width(300)
            .height(150)
          Text('鴻蒙操作系統')
        }
      }
      

      效果圖

      6卡片效果圖

      (3)創建卡片組件

      Card({ content: imageBuilder })
      

      7創建卡片

      另外,如果一個組件中只定義了一個@BuilderParam屬性,那么創建該組件時,也可直接通過"子組件"的方式傳入具體的UI結構,例如

      創建卡片組件

      Card() {
        Column({ space: 10 }) {
          Text('鴻蒙操作系統')
            .fontSize(25)
            .fontWeight(FontWeight.Bold)
          Text('鴻蒙操作系統是...')
        }
      }
      

      效果圖

      8傳遞子組件UI

      示例代碼

      pages/component/resue目錄下新建BuilderParamPage2.ets文件

      @Entry
      @Component
      struct BuilderParamPage2 {
        build() {
          Column({ space: 50 }) {
            //創建卡片組件(傳參)
            Card({ content: imageBuilder })
      
            //創建卡片組件("子組件")
            Card() {
              Column({ space: 10 }) {
                Text('鴻蒙操作系統')
                  .fontSize(25)
                  .fontWeight(FontWeight.Bold)
                Text('鴻蒙操作系統是一款由華為公司開發的多設備統一操作系統,致力于實現無縫連接和協同工作。其采用分布式架構,支持多終端智能互聯,提供高效、安全、流暢的用戶體驗。')
              }
            }
          }.width('100%')
          .height('100%')
          .justifyContent(FlexAlign.Center)
        }
      }
      
      //卡片內容
      @Builder function imageBuilder() {
        Column({ space: 10 }) {
          Image($r('app.media.img_harmony'))
            .width(300)
            .height(150)
          Text('鴻蒙操作系統')
        }
      }
      
      //卡片組件
      @Component
      struct Card {
        @BuilderParam content: () => void; //@BuilderParam屬性
      
        build() {
          Column() {
            this.content(); //占位符
          }.width('90%')
          .padding(10)
          .borderRadius(10)
          .shadow({ radius: 20 })
        }
      }
      

      《鴻蒙應用開發從入門到項目實戰》系列文章持續更新中,陸續更新AI+編程、企業級項目實戰等原創內容,防止迷路,歡迎關注!

      posted @ 2025-10-10 09:27  程序員潘Sir  閱讀(213)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 最近中文国语字幕在线播放| 日韩av片无码一区二区不卡 | 猫咪社区免费资源在线观看| 久久综合伊人| 国产69精品久久久久99尤物| 国产极品尤物粉嫩在线观看| 性欧美三级在线观看| 欧美偷窥清纯综合图区| av男人的天堂在线观看国产| 国产av精品一区二区三区| 狠狠综合久久综合88亚洲| 无码人妻aⅴ一区二区三区蜜桃| 亚洲中文字幕无码一久久区| 中文国产成人久久精品小说| 成人国产亚洲精品一区二区| 国产精品人成视频免费播放| 国产福利视频区一区二区| 敖汉旗| 国产亚洲精品第一综合另类| 4虎四虎永久在线精品免费| 成 人免费va视频| 男人和女人高潮做爰视频| 久久天天躁夜夜躁狠狠85| 久热这里有精品视频播放| 2019亚洲午夜无码天堂| 中文字幕av日韩有码| 久久婷婷成人综合色综合| 欧美成本人视频免费播放| 自拍偷拍第一区二区三区| 狠狠色丁香婷婷综合| 久久国产自偷自偷免费一区| 日韩精品无码一区二区视频 | 亚洲欧美人成人综合在线播放| 成人动漫综合网| 77se77亚洲欧美在线| 99久久伊人精品综合观看| 国产一区二区三区激情视频| 日韩人妻一区中文字幕| 日韩免费码中文在线观看| 女的被弄到高潮娇喘喷水视频| 精品久久久久久国产|