国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理

這篇具有很好參考價值的文章主要介紹了HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、狀態(tài)管理

在聲明式UI編程框架中,UI是程序狀態(tài)的運行結(jié)果,用戶構(gòu)建了一個UI模型,其中應(yīng)用的運行時的狀態(tài)是參數(shù)。當(dāng)參數(shù)改變時,UI作為返回結(jié)果,也將進(jìn)行對應(yīng)的改變。這些運行時的狀態(tài)變化所帶來的UI的重新渲染,在ArkUI中統(tǒng)稱為狀態(tài)管理機制。

自定義組件擁有變量,變量必須被裝飾器裝飾才可以成為狀態(tài)變量,狀態(tài)變量的改變會引起UI的渲染刷新。如果不使用狀態(tài)變量,UI只能在初始化時渲染,后續(xù)將不會再刷新。下圖展示了State和View(UI)之間的關(guān)系。

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

說明如下:

  • View(UI):UI渲染,一般指自定義組件的build方法和@Builder裝飾的方法內(nèi)的UI描述。
  • State:狀態(tài),一般指的是裝飾器裝飾的數(shù)據(jù)。用戶通過觸發(fā)組件的事件方法,改變狀態(tài)數(shù)據(jù)。狀態(tài)數(shù)據(jù)的改變,引起UI的重新渲染。

二、@State修飾符

@State?裝飾的變量是組件內(nèi)部的狀態(tài)數(shù)據(jù),當(dāng)這些狀態(tài)數(shù)據(jù)被修改時,將會調(diào)用所在組件的?build()?方法刷新UI。?@State?狀態(tài)數(shù)據(jù)具有以下特征:

  • @State裝飾器標(biāo)記的變量必須初始化,不能為空值
  • @state支持object、class、string、number、boolean、enum類型以及這些類型的數(shù)組
  • 嵌套類型以及數(shù)組中的對象屬性無法觸發(fā)視圖更新
  • 標(biāo)記為?@State?的屬性是私有變量,只能在組件內(nèi)訪問。

2.1.@State修飾符案例

創(chuàng)建StateExample01.ets,代碼如下:

@Entry
@Component
struct StateExample01 {
  @State message:string = "Hello World"

  build() {
    Column(){
      Text(this.message)
        .fontSize(50)
        .onClick(()=>{
          //變量通過@State修飾,點擊修改私有變量,然后會自動修改刷新UI
          this.message = "Hi Augus"
        })
    }
    .width("100%").height("100%")
    .justifyContent(FlexAlign.Center)//主軸方向?qū)R
  }
}

預(yù)覽效果如下:

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

2.2.@state修飾的私有變量類型

@state支持object、class、string、number、boolean、enum類型以及這些類型的數(shù)組,下面演示,點擊修改Sutdent對象的年齡屬性,點擊一次,頁面重新渲染一次:

class Student{
  sid:number
  name:string
  age:number

  constructor(sid:number,name:string,age:number) {
    this.sid = sid
    this.name = name
    this.age = age
  }
}

@Entry
@Component
struct StateExample02{
  //私有變量的值是一個對象
  @State s:Student = new Student(2301,"馬保國", 73)
  
  //@State必須初始化。否則會報錯
  //@State s:Student

  build() {
    Column(){
      Text(`${this.s.sid}:${this.s.name}:${this.s.age}`)
        .fontSize(30)
        .onClick(()=>{
          //變量通過@State修飾,點擊修改私有變量(點擊一次自增1),然后會自動修改刷新UI
          this.s.age++
        })
    }
    .width("100%").height("100%")
    .justifyContent(FlexAlign.Center)//主軸方向?qū)R
  }
}

預(yù)覽效果如下:

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

2.3.嵌套類型的對象屬性無法觸發(fā)視圖更新

下面的案例中Student對象嵌套了一個Pet對象,當(dāng)修改Pet對象屬性的時候,是無法觸發(fā)視圖的更新,下面的代碼中,點擊的時候雖然數(shù)據(jù)修改了,點擊界面并沒有修改,代碼如下:

class Student{
  sid:number
  name:string
  age:number
  //寵物
  pet:Pet

  constructor(sid:number,name:string,age:number,pet:Pet) {
    this.sid = sid
    this.name = name
    this.age = age
    this.pet = pet
  }
}

//寵物
class Pet{
  petName:string
  petAge:number

  constructor(petName:string,petAge:number) {
    this.petName = petName
    this.petAge = petAge
  }
}


@Entry
@Component
struct StateExample03{
  //私有變量的值是一個對象
  @State s:Student = new Student(2301,"馬保國", 73, new Pet("大黃",3))

  //@State必須初始化。否則會報錯
  //@State s:Student

  build() {
    Column(){
      //修改Student的屬性是可以的
      Text(`${this.s.sid}:${this.s.name}:${this.s.age}`)
        .fontSize(30)
        .onClick(()=>{
          //變量通過@State修飾,點擊修改私有變量(點擊一次自增1),然后會自動修改刷新UI
          this.s.age++
        })

      //修改Student的中包含的pet對象的屬性值,@State裝飾器是做不到的
      Text(`${this.s.pet.petName}:${this.s.pet.petAge}`)
        .fontSize(30)
        .onClick(()=>{
          //點擊修改變屬性的值
          this.s.pet.petAge++
        })
    }
    .width("100%").height("100%")
    .justifyContent(FlexAlign.Center)//主軸方向?qū)R
  }
}

預(yù)覽效果如下:

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

2.4.數(shù)組中的對象屬性無法觸發(fā)視圖更新

class Student{
  sid:number
  name:string
  age:number
  //寵物
  pet:Pet

  constructor(sid:number,name:string,age:number,pet:Pet) {
    this.sid = sid
    this.name = name
    this.age = age
    this.pet = pet
  }
}

//寵物
class Pet{
  petName:string
  petAge:number

  constructor(petName:string,petAge:number) {
    this.petName = petName
    this.petAge = petAge
  }
}

@Entry
@Component
struct StateExample03{
  //私有變量的值是一個對象
  @State s:Student = new Student(2301,"馬保國", 73, new Pet("大黃",3))

  //準(zhǔn)備一個數(shù)組
  @State pets:Pet[] = [new Pet("小白",2300), new Pet("小癡", 1100)]

  build() {
    Column({space:20}){
      //修改Student的屬性是可以的
      Text(`${this.s.sid}:${this.s.name}:${this.s.age}`)
        .fontSize(30)
        .onClick(()=>{
          //變量通過@State修飾,點擊修改私有變量(點擊一次自增1),然后會自動修改刷新UI
          this.s.age++
        })

      //添加寵物
      Button("添加").onClick(()=>{
        this.pets.push(new Pet("小灰"+1, 10))
      })

      Text("---------寵物列表------").fontSize(30).width("100%")
      ForEach(this.pets,(pet:Pet, index)=>{
        Row(){
          Text(`${pet.petName}:${pet.petAge}`).fontSize(20)
          Button("修改年齡").onClick(()=>{
            //點擊后發(fā)現(xiàn)修改了數(shù)據(jù),但是由于屬性屬于數(shù)組的對象,@State無法讓修改后自動渲染
            pet.petAge++
          })
        }.width("100%").justifyContent(FlexAlign.SpaceAround)

      })

    }
    .width("100%").height("100%")
    .justifyContent(FlexAlign.Center)//主軸方向?qū)R
  }
}

點擊修改的年齡是屬于,pets數(shù)組中對象的屬性,使用@State裝飾器無法觸發(fā)視圖的渲染,點擊頁面無法更新,預(yù)覽效果如下:

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

三、案例練習(xí)

這里實現(xiàn)如下效果,作為后續(xù)裝飾器講解的案例代碼。

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

代碼如下:

//任務(wù)類
class Task{
  static  id:number = 1;
  //任務(wù)名稱,id每次增加1
  name:string = `任務(wù)${Task.id++}`
  //任務(wù)狀態(tài),是否完成
  taskStatus:boolean = false
}

//統(tǒng)一的卡片樣式
@Styles function  card(){
  .width("90%")
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  //為當(dāng)前組件添加陰影效果
  .shadow({radius:6, color:"1F000000",offsetX:2,offsetY:4})
}

@Entry
@Component
struct StatusManagement {
  //總?cè)蝿?wù)數(shù)量
  @State totalTask:number = 0
  //已完成數(shù)量
  @State finishTask:number = 0

  //保存添加任務(wù)的數(shù)組
  @State tasks: Task[] = []

  //將跟新數(shù)據(jù)的操作進(jìn)一步抽取
  DataUpdate(){
    //需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
    this.totalTask = this.tasks.length
    //跟新已完成任務(wù)總數(shù)
    this.finishTask = this.tasks.filter(item=> item.taskStatus).length
  }

  //自定義刪除刪除
  @Builder DeleteTaskButton(index:number){
    Button(){
      Image($r("app.media.icon_remove_button"))
        .width(20)
        .fillColor("#B0E0E6")
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .onClick(()=>{
      //去數(shù)組中刪除
      this.tasks.splice(index, 1)

      /*//需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
      this.totalTask = this.tasks.length
      //跟新已完成任務(wù)總數(shù)
      this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/

      //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
      this.DataUpdate()
    })
    .backgroundColor(Color.Red)
    .margin(10)
  }

  build() {
    Column({space:20}){
      //1.任務(wù)進(jìn)度
      Row(){
        Text("任務(wù)進(jìn)度:")
          .fontSize(30) //字體大小
          .fontWeight(FontWeight.Bold)//字體加粗

        //環(huán)形和數(shù)字要使用堆疊容器,
        Stack(){
          //環(huán)形組件: 進(jìn)度、總量、樣式
          Progress({value:this.finishTask, total:this.totalTask,type:ProgressType.Ring})
            .width(90)
          Row(){//讓數(shù)字顯示在一起,放在一個容器中
            //任務(wù)完成量
            Text(`${this.finishTask}`)
              .fontSize(25) //字體大小
              .fontColor("#0000CD")

            //任務(wù)總量
            Text(` / ${this.totalTask}`)
              .fontSize(25) //字體大小
          }
        }

      }
      .width("100%")
      .margin({top:20,bottom:20})
      .justifyContent(FlexAlign.SpaceAround) //主軸方向布局
      .card()

      //2.添加任務(wù)按鈕
      Button("添加任務(wù)")
        .width(200)
        .onClick(()=>{
          //1.添加任務(wù),就是給任務(wù)數(shù)組中添加一個值
          this.tasks.push(new Task())
          //2.新增任務(wù)后,需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
          this.totalTask = this.tasks.length
        })

      //3.任務(wù)列表
      List({space:5}){
        ForEach(this.tasks,(item:Task, index:number)=>{
          ListItem(){
            Row(){
              //文本
              Text(item.name).fontColor(20)
              //單選框,select決定是否選中,類型布爾值,取Task對象屬性taskStatus
              Checkbox()
                .select(item.taskStatus)
                .onChange((value:boolean)=>{
                  //1.更新當(dāng)前已完成任務(wù)狀態(tài),勾選后修改狀態(tài)為true
                  item.taskStatus = value

                  /*//2.統(tǒng)計已完成的數(shù)量,就是統(tǒng)計數(shù)組中狀態(tài)為true的元素個數(shù)
                  this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/
                  //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
                  this.DataUpdate()
                })
            }
            .width("100%")
            .card()
            .justifyContent(FlexAlign.SpaceBetween)
          }
          /**
           * 用于設(shè)置ListItem的劃出組件。
           * - start: ListItem向右劃動時item左邊的組件(List垂直布局時)或ListItem向下劃動時item上方的組件(List水平布局時)。
           * - end: ListItem向左劃動時item右邊的組件(List垂直布局時)或ListItem向上劃動時item下方的組件(List水平布局時)。
           * - edgeEffect: 滑動效果。
           */
          .swipeAction({end: this.DeleteTaskButton(index)})
        })
      }
      .width("100%")
      .layoutWeight(1) //忽略元素本身尺寸設(shè)置,表示自適應(yīng)占滿剩余空間。
      .alignListItem(ListItemAlign.Center) //ListItem在List交叉軸方向的布局方式(這里就是水平方向居中對齊),默認(rèn)為首部對齊。
    }
    .size({width:"100%",height:"100%"})
    .backgroundColor("#F0F8FF")
  }
}

四、@Prop和@Link

之前章節(jié)的時候,我們吧所有的代碼都寫在一起,這樣會導(dǎo)致代碼的可讀性很差,所以我們會把功能封裝成不同的組件

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

這時候在父子組件需要進(jìn)行數(shù)據(jù)同步的時候,可以通過@Prop和@Link裝飾器來做到。在父組件中用@State裝飾,在自組件中用@Prop或@Link裝飾。

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

說明:

  • @Prop用于子組件只監(jiān)聽父組件的數(shù)據(jù)改變而改變,自己不對數(shù)據(jù)改變,俗稱單項同步
  • @Link用于子組件與父組件都會對數(shù)據(jù)改變,都需要在數(shù)據(jù)改變的時候發(fā)生相應(yīng)的更新。俗稱雙向同步

4.1.@Prop裝飾器

將章節(jié)二中的代碼,數(shù)據(jù)統(tǒng)計和展示分別抽取成兩個子組件,這里先抽取出來數(shù)據(jù)統(tǒng)計部分,代碼如下:

//任務(wù)類
class Task{
  static  id:number = 1;
  //任務(wù)名稱,id每次增加1
  name:string = `任務(wù)${Task.id++}`
  //任務(wù)狀態(tài),是否完成
  taskStatus:boolean = false
}

//統(tǒng)一的卡片樣式
@Styles function  card(){
  .width("90%")
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  //為當(dāng)前組件添加陰影效果
  .shadow({radius:6, color:"1F000000",offsetX:2,offsetY:4})
}

@Entry
@Component
struct StatusManagement {
  //總?cè)蝿?wù)數(shù)量
  @State totalTask:number = 0
  //已完成數(shù)量
  @State finishTask:number = 0

  //保存添加任務(wù)的數(shù)組
  @State tasks: Task[] = []

  //將跟新數(shù)據(jù)的操作進(jìn)一步抽取
  DataUpdate(){
    //需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
    this.totalTask = this.tasks.length
    //跟新已完成任務(wù)總數(shù)
    this.finishTask = this.tasks.filter(item=> item.taskStatus).length
  }

  //自定義刪除刪除
  @Builder DeleteTaskButton(index:number){
    Button(){
      Image($r("app.media.icon_remove_button"))
        .width(20)
        .fillColor("#B0E0E6")
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .onClick(()=>{
      //去數(shù)組中刪除
      this.tasks.splice(index, 1)

      /*//需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
      this.totalTask = this.tasks.length
      //跟新已完成任務(wù)總數(shù)
      this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/

      //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
      this.DataUpdate()
    })
    .backgroundColor(Color.Red)
    .margin(10)
  }

  build() {
    Column({space:20}){
      //1.任務(wù)進(jìn)度 這里直接調(diào)用自定義的組件
      TaskStatusProgress({totalTask:this.totalTask, finishTask: this.finishTask})

      //2.添加任務(wù)按鈕
      Button("添加任務(wù)")
        .width(200)
        .onClick(()=>{
          //1.添加任務(wù),就是給任務(wù)數(shù)組中添加一個值
          this.tasks.push(new Task())
          //2.新增任務(wù)后,需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
          this.totalTask = this.tasks.length
        })

      //3.任務(wù)列表
      List({space:5}){
        ForEach(this.tasks,(item:Task, index:number)=>{
          ListItem(){
            Row(){
              //文本
              Text(item.name).fontColor(20)
              //單選框,select決定是否選中,類型布爾值,取Task對象屬性taskStatus
              Checkbox()
                .select(item.taskStatus)
                .onChange((value:boolean)=>{
                  //1.更新當(dāng)前已完成任務(wù)狀態(tài),勾選后修改狀態(tài)為true
                  item.taskStatus = value

                  /*//2.統(tǒng)計已完成的數(shù)量,就是統(tǒng)計數(shù)組中狀態(tài)為true的元素個數(shù)
                  this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/
                  //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
                  this.DataUpdate()
                })
            }
            .width("100%")
            .card()
            .justifyContent(FlexAlign.SpaceBetween)
          }
          /**
           * 用于設(shè)置ListItem的劃出組件。
           * - start: ListItem向右劃動時item左邊的組件(List垂直布局時)或ListItem向下劃動時item上方的組件(List水平布局時)。
           * - end: ListItem向左劃動時item右邊的組件(List垂直布局時)或ListItem向上劃動時item下方的組件(List水平布局時)。
           * - edgeEffect: 滑動效果。
           */
          .swipeAction({end: this.DeleteTaskButton(index)})
        })
      }
      .width("100%")
      .layoutWeight(1) //忽略元素本身尺寸設(shè)置,表示自適應(yīng)占滿剩余空間。
      .alignListItem(ListItemAlign.Center) //ListItem在List交叉軸方向的布局方式(這里就是水平方向居中對齊),默認(rèn)為首部對齊。
    }
    .size({width:"100%",height:"100%"})
    .backgroundColor("#F0F8FF")
  }
}

/**
 * 定義任務(wù)進(jìn)度組件
 * 使用@Prop裝飾器,監(jiān)控父組件的數(shù)據(jù)狀態(tài),而改變自身的數(shù)據(jù)
 */
@Component
struct TaskStatusProgress {
  //TODO “@Prop”、“@Link”修飾的變量不允許在本地初始化
  //總?cè)蝿?wù)數(shù)量
  @Prop totalTask:number
  //已完成數(shù)量
  @Prop finishTask:number

  build() {
    //1.任務(wù)進(jìn)度
    Row(){
      Text("任務(wù)進(jìn)度:")
        .fontSize(30) //字體大小
        .fontWeight(FontWeight.Bold)//字體加粗

      //環(huán)形和數(shù)字要使用堆疊容器,
      Stack(){
        //環(huán)形組件: 進(jìn)度、總量、樣式
        Progress({value:this.finishTask, total:this.totalTask,type:ProgressType.Ring})
          .width(90)
        Row(){//讓數(shù)字顯示在一起,放在一個容器中
          //任務(wù)完成量
          Text(`${this.finishTask}`)
            .fontSize(25) //字體大小
            .fontColor("#0000CD")

          //任務(wù)總量
          Text(` / ${this.totalTask}`)
            .fontSize(25) //字體大小
        }
      }
    }
    .width("100%")
    .margin({top:20,bottom:20})
    .justifyContent(FlexAlign.SpaceAround) //主軸方向布局
    .card()
  }
}

上面的代碼將任務(wù)進(jìn)度抽取成組件TaskStatusProgress ,然后在調(diào)用即可,但是需要注意的是,作為子組件TaskStatusProgress?,只需要監(jiān)控父組件的任務(wù)總量和已完成任務(wù)的值,然后自己進(jìn)行渲染即可,并不需要改變數(shù)據(jù),所以在TaskStatusProgress 子組件中定義任務(wù)總量和任務(wù)進(jìn)度變量的時候,使用@Prop裝飾器。

4.2.@Link裝飾器

將新增任務(wù)按鈕和任務(wù)列表抽取成第二個子組件TaskList,由于TaskList子組件本身需要修改數(shù)據(jù)(任務(wù)總量和已完成任務(wù)進(jìn)度),同時父組件需要感知到子組件的修改,將數(shù)據(jù)傳入到上一章節(jié)定義TaskStatusProgress子組件中,進(jìn)行數(shù)據(jù)展示,所以這是一個雙向的數(shù)據(jù)同步,需要在子組件中定義變量任務(wù)總量和已完成任務(wù)的時候使用@Link裝飾器實現(xiàn)雙向的數(shù)據(jù)同步。但是需要注意的是,在父組件調(diào)用TaskLink子組件的時候,傳入?yún)?shù)的時候需要使用$,同時不能使用this,才可以如下:

//2.任務(wù)列表
TaskList({totalTask: $totalTask, finishTask:$finishTask})

子組件TaskList如下:

/**
 * 定義任務(wù)列表子組件
 */
@Component
struct TaskList {
  //總?cè)蝿?wù)數(shù)量
  @Link totalTask:number
  //已完成數(shù)量
  @Link finishTask:number

  //保存添加任務(wù)的數(shù)組
  @State tasks: Task[] = []

  //將跟新數(shù)據(jù)的操作進(jìn)一步抽取
  DataUpdate(){
    //需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
    this.totalTask = this.tasks.length
    //跟新已完成任務(wù)總數(shù)
    this.finishTask = this.tasks.filter(item=> item.taskStatus).length
  }

  //自定義刪除刪除
  @Builder DeleteTaskButton(index:number){
    Button(){
      Image($r("app.media.icon_remove_button"))
        .width(20)
        .fillColor("#B0E0E6")
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .onClick(()=>{
      //去數(shù)組中刪除
      this.tasks.splice(index, 1)

      /*//需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
      this.totalTask = this.tasks.length
      //跟新已完成任務(wù)總數(shù)
      this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/

      //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
      this.DataUpdate()
    })
    .backgroundColor(Color.Red)
    .margin(10)
  }

  build() {
    Column(){
      //2.添加任務(wù)按鈕
      Button("添加任務(wù)")
        .width(200)
        .onClick(()=>{
          //1.添加任務(wù),就是給任務(wù)數(shù)組中添加一個值
          this.tasks.push(new Task())
          //2.新增任務(wù)后,需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
          this.totalTask = this.tasks.length
        })

      //3.任務(wù)列表
      List({space:5}){
        ForEach(this.tasks,(item:Task, index:number)=>{
          ListItem(){
            Row(){
              //文本
              Text(item.name).fontColor(20)
              //單選框,select決定是否選中,類型布爾值,取Task對象屬性taskStatus
              Checkbox()
                .select(item.taskStatus)
                .onChange((value:boolean)=>{
                  //1.更新當(dāng)前已完成任務(wù)狀態(tài),勾選后修改狀態(tài)為true
                  item.taskStatus = value

                  /*//2.統(tǒng)計已完成的數(shù)量,就是統(tǒng)計數(shù)組中狀態(tài)為true的元素個數(shù)
                  this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/
                  //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
                  this.DataUpdate()
                })
            }
            .width("100%")
            .card()
            .justifyContent(FlexAlign.SpaceBetween)
          }
          /**
           * 用于設(shè)置ListItem的劃出組件。
           * - start: ListItem向右劃動時item左邊的組件(List垂直布局時)或ListItem向下劃動時item上方的組件(List水平布局時)。
           * - end: ListItem向左劃動時item右邊的組件(List垂直布局時)或ListItem向上劃動時item下方的組件(List水平布局時)。
           * - edgeEffect: 滑動效果。
           */
          .swipeAction({end: this.DeleteTaskButton(index)})
        })
      }
      .width("100%")
      .layoutWeight(1) //忽略元素本身尺寸設(shè)置,表示自適應(yīng)占滿剩余空間。
      .alignListItem(ListItemAlign.Center) //ListItem在List交叉軸方向的布局方式(這里就是水平方向居中對齊),默認(rèn)為首部對齊。
    }.width("100%").height("100%")
  }
}

完整的代碼如下:

//任務(wù)類
class Task{
  static  id:number = 1;
  //任務(wù)名稱,id每次增加1
  name:string = `任務(wù)${Task.id++}`
  //任務(wù)狀態(tài),是否完成
  taskStatus:boolean = false
}

//統(tǒng)一的卡片樣式
@Styles function  card(){
  .width("90%")
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  //為當(dāng)前組件添加陰影效果
  .shadow({radius:6, color:"1F000000",offsetX:2,offsetY:4})
}

@Entry
@Component
struct StatusManagement {
  //總?cè)蝿?wù)數(shù)量
  @State totalTask:number = 0
  //已完成數(shù)量
  @State finishTask:number = 0

  //保存添加任務(wù)的數(shù)組
  //@State tasks: Task[] = []

  build() {
    Column({space:20}){
      //1.任務(wù)進(jìn)度 這里直接調(diào)用自定義的組件
      TaskStatusProgress({totalTask:this.totalTask, finishTask: this.finishTask})

      //2.任務(wù)列表
      TaskList({totalTask: $totalTask, finishTask:$finishTask})
    }
    .size({width:"100%",height:"100%"})
    .backgroundColor("#F0F8FF")
  }
}

/**
 * 定義任務(wù)進(jìn)度組件
 * 使用@Prop裝飾器,監(jiān)控父組件的數(shù)據(jù)狀態(tài),而改變自身的數(shù)據(jù)
 */
@Component
struct TaskStatusProgress {
  //TODO “@Prop”、“@Link”修飾的變量不允許在本地初始化
  //總?cè)蝿?wù)數(shù)量
  @Prop totalTask:number
  //已完成數(shù)量
  @Prop finishTask:number

  build() {
    //1.任務(wù)進(jìn)度
    Row(){
      Text("任務(wù)進(jìn)度:")
        .fontSize(30) //字體大小
        .fontWeight(FontWeight.Bold)//字體加粗

      //環(huán)形和數(shù)字要使用堆疊容器,
      Stack(){
        //環(huán)形組件: 進(jìn)度、總量、樣式
        Progress({value:this.finishTask, total:this.totalTask,type:ProgressType.Ring})
          .width(90)
        Row(){//讓數(shù)字顯示在一起,放在一個容器中
          //任務(wù)完成量
          Text(`${this.finishTask}`)
            .fontSize(25) //字體大小
            .fontColor("#0000CD")

          //任務(wù)總量
          Text(` / ${this.totalTask}`)
            .fontSize(25) //字體大小
        }
      }
    }
    .width("100%")
    .margin({top:20,bottom:20})
    .justifyContent(FlexAlign.SpaceAround) //主軸方向布局
    .card()
  }
}

/**
 * 定義任務(wù)列表子組件
 */
@Component
struct TaskList {
  //總?cè)蝿?wù)數(shù)量
  @Link totalTask:number
  //已完成數(shù)量
  @Link finishTask:number

  //保存添加任務(wù)的數(shù)組
  @State tasks: Task[] = []

  //將跟新數(shù)據(jù)的操作進(jìn)一步抽取
  DataUpdate(){
    //需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
    this.totalTask = this.tasks.length
    //跟新已完成任務(wù)總數(shù)
    this.finishTask = this.tasks.filter(item=> item.taskStatus).length
  }

  //自定義刪除刪除
  @Builder DeleteTaskButton(index:number){
    Button(){
      Image($r("app.media.icon_remove_button"))
        .width(20)
        .fillColor("#B0E0E6")
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .onClick(()=>{
      //去數(shù)組中刪除
      this.tasks.splice(index, 1)

      /*//需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
      this.totalTask = this.tasks.length
      //跟新已完成任務(wù)總數(shù)
      this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/

      //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
      this.DataUpdate()
    })
    .backgroundColor(Color.Red)
    .margin(10)
  }

  build() {
    Column(){
      //2.添加任務(wù)按鈕
      Button("添加任務(wù)")
        .width(200)
        .onClick(()=>{
          //1.添加任務(wù),就是給任務(wù)數(shù)組中添加一個值
          this.tasks.push(new Task())
          //2.新增任務(wù)后,需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
          this.totalTask = this.tasks.length
        })

      //3.任務(wù)列表
      List({space:5}){
        ForEach(this.tasks,(item:Task, index:number)=>{
          ListItem(){
            Row(){
              //文本
              Text(item.name).fontColor(20)
              //單選框,select決定是否選中,類型布爾值,取Task對象屬性taskStatus
              Checkbox()
                .select(item.taskStatus)
                .onChange((value:boolean)=>{
                  //1.更新當(dāng)前已完成任務(wù)狀態(tài),勾選后修改狀態(tài)為true
                  item.taskStatus = value

                  /*//2.統(tǒng)計已完成的數(shù)量,就是統(tǒng)計數(shù)組中狀態(tài)為true的元素個數(shù)
                  this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/
                  //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
                  this.DataUpdate()
                })
            }
            .width("100%")
            .card()
            .justifyContent(FlexAlign.SpaceBetween)
          }
          /**
           * 用于設(shè)置ListItem的劃出組件。
           * - start: ListItem向右劃動時item左邊的組件(List垂直布局時)或ListItem向下劃動時item上方的組件(List水平布局時)。
           * - end: ListItem向左劃動時item右邊的組件(List垂直布局時)或ListItem向上劃動時item下方的組件(List水平布局時)。
           * - edgeEffect: 滑動效果。
           */
          .swipeAction({end: this.DeleteTaskButton(index)})
        })
      }
      .width("100%")
      .layoutWeight(1) //忽略元素本身尺寸設(shè)置,表示自適應(yīng)占滿剩余空間。
      .alignListItem(ListItemAlign.Center) //ListItem在List交叉軸方向的布局方式(這里就是水平方向居中對齊),默認(rèn)為首部對齊。
    }.width("100%").height("100%")
  }
}

4.2.變量數(shù)據(jù)類型說明

@Prop和@Link變量類型和初始化方式說明如下:

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

需要注意的是,數(shù)據(jù)同步的時候:

  • @Prop父組件是對象類型,則子組件是對象屬性
  • @Link父子類型一致

1)Prop父組件變量是對象類型,則子組件是對象屬性,這里以TaskStatusProgress任務(wù)進(jìn)度子組件進(jìn)行演示,因為TaskList必須是雙向同步,父組件才可以知道數(shù)據(jù)變化,必須使用@Link

//任務(wù)類
class Task{
  static  id:number = 1;
  //任務(wù)名稱,id每次增加1
  name:string = `任務(wù)${Task.id++}`
  //任務(wù)狀態(tài),是否完成
  taskStatus:boolean = false
}

//統(tǒng)一的卡片樣式
@Styles function  card(){
  .width("90%")
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  //為當(dāng)前組件添加陰影效果
  .shadow({radius:6, color:"1F000000",offsetX:2,offsetY:4})
}

//將統(tǒng)計信息抽取出來形成一個類
class StateInfo{
  //總?cè)蝿?wù)數(shù)量
  totalTask:number
  //已完成數(shù)量
  finishTask:number

  constructor( totalTask:number = 0,finishTask:number = 0 ) {
    this.totalTask = totalTask
    this.finishTask = finishTask
  }
}

@Entry
@Component
struct StatusManagement {
  //TODO 父子組件變量類型是對象, @Prop子組件變量類型是對象的屬性
  //創(chuàng)建統(tǒng)計信息對象
  @State stat: StateInfo = new StateInfo()

  build() {
    Column({space:20}){
      //1.任務(wù)進(jìn)度 這里直接調(diào)用自定義的組件,使用的是@Prop,通過屬性傳入
      TaskStatusProgress({totalTask:this.stat.totalTask, finishTask: this.stat.finishTask})

      //2.任務(wù)列表
      //TODO 子組件使用的@Link, 通過$符的方式傳值
      TaskList({stat:$stat})
    }
    .size({width:"100%",height:"100%"})
    .backgroundColor("#F0F8FF")
  }
}

/**
 * 定義任務(wù)進(jìn)度組件
 * 使用@Prop裝飾器,監(jiān)控父組件的數(shù)據(jù)狀態(tài),而改變自身的數(shù)據(jù)
 */
@Component
struct TaskStatusProgress {
  //TODO 父組件是對象,子組件則可以使用“@Prop”作為對象的屬性
  //總?cè)蝿?wù)數(shù)量
  @Prop totalTask:number
  //已完成數(shù)量
  @Prop finishTask:number

  build() {
    //1.任務(wù)進(jìn)度
    Row(){
      Text("任務(wù)進(jìn)度:")
        .fontSize(30) //字體大小
        .fontWeight(FontWeight.Bold)//字體加粗

      //環(huán)形和數(shù)字要使用堆疊容器,
      Stack(){
        //環(huán)形組件: 進(jìn)度、總量、樣式
        Progress({value:this.finishTask, total:this.totalTask,type:ProgressType.Ring})
          .width(90)
        Row(){//讓數(shù)字顯示在一起,放在一個容器中
          //任務(wù)完成量
          Text(`${this.finishTask}`)
            .fontSize(25) //字體大小
            .fontColor("#0000CD")

          //任務(wù)總量
          Text(` / ${this.totalTask}`)
            .fontSize(25) //字體大小
        }
      }
    }
    .width("100%")
    .margin({top:20,bottom:20})
    .justifyContent(FlexAlign.SpaceAround) //主軸方向布局
    .card()
  }
}

/**
 * 定義任務(wù)列表子組件
 */
@Component
struct TaskList {
  //TODO
  @Link stat: StateInfo

  //保存添加任務(wù)的數(shù)組
  @State tasks: Task[] = []

  //將跟新數(shù)據(jù)的操作進(jìn)一步抽取
  DataUpdate(){
    //需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
    this.stat.totalTask = this.tasks.length
    //跟新已完成任務(wù)總數(shù)
    this.stat.finishTask = this.tasks.filter(item=> item.taskStatus).length
  }

  //自定義刪除刪除
  @Builder DeleteTaskButton(index:number){
    Button(){
      Image($r("app.media.icon_remove_button"))
        .width(20)
        .fillColor("#B0E0E6")
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .onClick(()=>{
      //去數(shù)組中刪除
      this.tasks.splice(index, 1)

      //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
      this.DataUpdate()
    })
    .backgroundColor(Color.Red)
    .margin(10)
  }

  build() {
    Column(){
      //2.添加任務(wù)按鈕
      Button("添加任務(wù)")
        .width(200)
        .onClick(()=>{
          //1.添加任務(wù),就是給任務(wù)數(shù)組中添加一個值
          this.tasks.push(new Task())
          //2.新增任務(wù)后,需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
          this.stat.totalTask = this.tasks.length
        })

      //3.任務(wù)列表
      List({space:5}){
        ForEach(this.tasks,(item:Task, index:number)=>{
          ListItem(){
            Row(){
              //文本
              Text(item.name).fontColor(20)
              //單選框,select決定是否選中,類型布爾值,取Task對象屬性taskStatus
              Checkbox()
                .select(item.taskStatus)
                .onChange((value:boolean)=>{
                  //1.更新當(dāng)前已完成任務(wù)狀態(tài),勾選后修改狀態(tài)為true
                  item.taskStatus = value

                  /*//2.統(tǒng)計已完成的數(shù)量,就是統(tǒng)計數(shù)組中狀態(tài)為true的元素個數(shù)
                  this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/
                  //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
                  this.DataUpdate()
                })
            }
            .width("100%")
            .card()
            .justifyContent(FlexAlign.SpaceBetween)
          }
          /**
           * 用于設(shè)置ListItem的劃出組件。
           * - start: ListItem向右劃動時item左邊的組件(List垂直布局時)或ListItem向下劃動時item上方的組件(List水平布局時)。
           * - end: ListItem向左劃動時item右邊的組件(List垂直布局時)或ListItem向上劃動時item下方的組件(List水平布局時)。
           * - edgeEffect: 滑動效果。
           */
          .swipeAction({end: this.DeleteTaskButton(index)})
        })
      }
      .width("100%")
      .layoutWeight(1) //忽略元素本身尺寸設(shè)置,表示自適應(yīng)占滿剩余空間。
      .alignListItem(ListItemAlign.Center) //ListItem在List交叉軸方向的布局方式(這里就是水平方向居中對齊),默認(rèn)為首部對齊。
    }.width("100%").height("100%")
  }
}

2)@Link演示,父子組件變量同為對象

//任務(wù)類
class Task{
  static  id:number = 1;
  //任務(wù)名稱,id每次增加1
  name:string = `任務(wù)${Task.id++}`
  //任務(wù)狀態(tài),是否完成
  taskStatus:boolean = false
}

//統(tǒng)一的卡片樣式
@Styles function  card(){
  .width("90%")
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  //為當(dāng)前組件添加陰影效果
  .shadow({radius:6, color:"1F000000",offsetX:2,offsetY:4})
}

//將統(tǒng)計信息抽取出來形成一個類
class StateInfo{
  //總?cè)蝿?wù)數(shù)量
  totalTask:number
  //已完成數(shù)量
  finishTask:number

  constructor( totalTask:number = 0,finishTask:number = 0 ) {
    this.totalTask = totalTask
    this.finishTask = finishTask
  }
}

@Entry
@Component
struct StatusManagement {
  //TODO @Link 父子組件變量類型都可以是對象
  //創(chuàng)建統(tǒng)計信息對象
  @State stat: StateInfo = new StateInfo()

  build() {
    Column({space:20}){
      //1.任務(wù)進(jìn)度 這里直接調(diào)用自定義的組件
      TaskStatusProgress({totalTask:this.stat.totalTask, finishTask: this.stat.finishTask})

      //2.任務(wù)列表
      //TODO 這里任然使用$參數(shù)名的形式
      TaskList({stat:$stat})
    }
    .size({width:"100%",height:"100%"})
    .backgroundColor("#F0F8FF")
  }
}

/**
 * 定義任務(wù)進(jìn)度組件
 * 使用@Prop裝飾器,監(jiān)控父組件的數(shù)據(jù)狀態(tài),而改變自身的數(shù)據(jù)
 */
@Component
struct TaskStatusProgress {
  //TODO “@Prop”、“@Link”修飾的變量不允許在本地初始化
  //總?cè)蝿?wù)數(shù)量
  @Prop totalTask:number
  //已完成數(shù)量
  @Prop finishTask:number

  build() {
    //1.任務(wù)進(jìn)度
    Row(){
      Text("任務(wù)進(jìn)度:")
        .fontSize(30) //字體大小
        .fontWeight(FontWeight.Bold)//字體加粗

      //環(huán)形和數(shù)字要使用堆疊容器,
      Stack(){
        //環(huán)形組件: 進(jìn)度、總量、樣式
        Progress({value:this.finishTask, total:this.totalTask,type:ProgressType.Ring})
          .width(90)
        Row(){//讓數(shù)字顯示在一起,放在一個容器中
          //任務(wù)完成量
          Text(`${this.finishTask}`)
            .fontSize(25) //字體大小
            .fontColor("#0000CD")

          //任務(wù)總量
          Text(` / ${this.totalTask}`)
            .fontSize(25) //字體大小
        }
      }
    }
    .width("100%")
    .margin({top:20,bottom:20})
    .justifyContent(FlexAlign.SpaceAround) //主軸方向布局
    .card()
  }
}

/**
 * 定義任務(wù)列表子組件
 */
@Component
struct TaskList {
  //TODO @Link 父子組件變量類型都可以是對象
  //總?cè)蝿?wù)數(shù)量
  @Link stat:StateInfo

  //保存添加任務(wù)的數(shù)組
  @State tasks: Task[] = []

  //將跟新數(shù)據(jù)的操作進(jìn)一步抽取
  DataUpdate(){
    //需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
    this.stat.totalTask = this.tasks.length
    //跟新已完成任務(wù)總數(shù)
    this.stat.finishTask = this.tasks.filter(item=> item.taskStatus).length
  }

  //自定義刪除刪除
  @Builder DeleteTaskButton(index:number){
    Button(){
      Image($r("app.media.icon_remove_button"))
        .width(20)
        .fillColor("#B0E0E6")
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .onClick(()=>{
      //去數(shù)組中刪除
      this.tasks.splice(index, 1)

      /*//需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
      this.totalTask = this.tasks.length
      //跟新已完成任務(wù)總數(shù)
      this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/

      //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
      this.DataUpdate()
    })
    .backgroundColor(Color.Red)
    .margin(10)
  }

  build() {
    Column(){
      //2.添加任務(wù)按鈕
      Button("添加任務(wù)")
        .width(200)
        .onClick(()=>{
          //1.添加任務(wù),就是給任務(wù)數(shù)組中添加一個值
          this.tasks.push(new Task())
          //2.新增任務(wù)后,需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
          this.stat.totalTask = this.tasks.length
        })

      //3.任務(wù)列表
      List({space:5}){
        ForEach(this.tasks,(item:Task, index:number)=>{
          ListItem(){
            Row(){
              //文本
              Text(item.name).fontColor(20)
              //單選框,select決定是否選中,類型布爾值,取Task對象屬性taskStatus
              Checkbox()
                .select(item.taskStatus)
                .onChange((value:boolean)=>{
                  //1.更新當(dāng)前已完成任務(wù)狀態(tài),勾選后修改狀態(tài)為true
                  item.taskStatus = value

                  /*//2.統(tǒng)計已完成的數(shù)量,就是統(tǒng)計數(shù)組中狀態(tài)為true的元素個數(shù)
                  this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/
                  //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
                  this.DataUpdate()
                })
            }
            .width("100%")
            .card()
            .justifyContent(FlexAlign.SpaceBetween)
          }
          /**
           * 用于設(shè)置ListItem的劃出組件。
           * - start: ListItem向右劃動時item左邊的組件(List垂直布局時)或ListItem向下劃動時item上方的組件(List水平布局時)。
           * - end: ListItem向左劃動時item右邊的組件(List垂直布局時)或ListItem向上劃動時item下方的組件(List水平布局時)。
           * - edgeEffect: 滑動效果。
           */
          .swipeAction({end: this.DeleteTaskButton(index)})
        })
      }
      .width("100%")
      .layoutWeight(1) //忽略元素本身尺寸設(shè)置,表示自適應(yīng)占滿剩余空間。
      .alignListItem(ListItemAlign.Center) //ListItem在List交叉軸方向的布局方式(這里就是水平方向居中對齊),默認(rèn)為首部對齊。
    }.width("100%").height("100%")
  }
}

五、@Provide和Consume

@Provide和Consume可以跨組件提供類似于@State和@Link的雙向同步。如下圖所示:

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

但是需要注意 :

  • @Provide:父組件使用
  • @Consume:子組件或者后代組件使用
  • 同時在在調(diào)用子組件或者后代組件的時候,子組件或者后代組件定義了參數(shù),也是不需要傳入,會自動隱式的傳入

代碼案例如下:

//任務(wù)類
class Task{
  static  id:number = 1;
  //任務(wù)名稱,id每次增加1
  name:string = `任務(wù)${Task.id++}`
  //任務(wù)狀態(tài),是否完成
  taskStatus:boolean = false
}

//統(tǒng)一的卡片樣式
@Styles function  card(){
  .width("90%")
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  //為當(dāng)前組件添加陰影效果
  .shadow({radius:6, color:"1F000000",offsetX:2,offsetY:4})
}

//將統(tǒng)計信息抽取出來形成一個類
class StateInfo{
  //總?cè)蝿?wù)數(shù)量
  totalTask:number
  //已完成數(shù)量
  finishTask:number

  constructor( totalTask:number = 0,finishTask:number = 0 ) {
    this.totalTask = totalTask
    this.finishTask = finishTask
  }
}

@Entry
@Component
struct StatusManagement {
  //TODO 父子組件變量類型是對象, @Prop子組件變量類型是對象的屬性
  //創(chuàng)建統(tǒng)計信息對象
  @Provide stat: StateInfo = new StateInfo()

  build() {
    Column({space:20}){
      //1.任務(wù)進(jìn)度 這里直接調(diào)用自定義的組件,使用的是@Prop,通過屬性傳入
      TaskStatusProgress()

      //2.任務(wù)列表
      //TODO 子組件使用的@Link, 通過$符的方式傳值
      TaskList()
    }
    .size({width:"100%",height:"100%"})
    .backgroundColor("#F0F8FF")
  }
}

/**
 * 定義任務(wù)進(jìn)度組件
 * 使用@Prop裝飾器,監(jiān)控父組件的數(shù)據(jù)狀態(tài),而改變自身的數(shù)據(jù)
 */
@Component
struct TaskStatusProgress {
  //TODO 通過@Consume實現(xiàn)雙向同步,調(diào)用組件的時候不需要傳入值,會自動傳入
  @Consume stat: StateInfo

  build() {
    //1.任務(wù)進(jìn)度
    Row(){
      Text("任務(wù)進(jìn)度:")
        .fontSize(30) //字體大小
        .fontWeight(FontWeight.Bold)//字體加粗

      //環(huán)形和數(shù)字要使用堆疊容器,
      Stack(){
        //環(huán)形組件: 進(jìn)度、總量、樣式
        Progress({value:this.stat.finishTask, total:this.stat.totalTask,type:ProgressType.Ring})
          .width(90)
        Row(){//讓數(shù)字顯示在一起,放在一個容器中
          //任務(wù)完成量
          Text(`${this.stat.finishTask}`)
            .fontSize(25) //字體大小
            .fontColor("#0000CD")

          //任務(wù)總量
          Text(` / ${this.stat.totalTask}`)
            .fontSize(25) //字體大小
        }
      }
    }
    .width("100%")
    .margin({top:20,bottom:20})
    .justifyContent(FlexAlign.SpaceAround) //主軸方向布局
    .card()
  }
}

/**
 * 定義任務(wù)列表子組件
 */
@Component
struct TaskList {
  //TODO 通過@Consume實現(xiàn)雙向同步,調(diào)用組件的時候不需要傳入值,會自動傳入
  @Consume stat: StateInfo

  //保存添加任務(wù)的數(shù)組
  @State tasks: Task[] = []

  //將跟新數(shù)據(jù)的操作進(jìn)一步抽取
  DataUpdate(){
    //需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
    this.stat.totalTask = this.tasks.length
    //跟新已完成任務(wù)總數(shù)
    this.stat.finishTask = this.tasks.filter(item=> item.taskStatus).length
  }

  //自定義刪除刪除
  @Builder DeleteTaskButton(index:number){
    Button(){
      Image($r("app.media.icon_remove_button"))
        .width(20)
        .fillColor("#B0E0E6")
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .onClick(()=>{
      //去數(shù)組中刪除
      this.tasks.splice(index, 1)

      //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
      this.DataUpdate()
    })
    .backgroundColor(Color.Red)
    .margin(10)
  }

  build() {
    Column(){
      //2.添加任務(wù)按鈕
      Button("添加任務(wù)")
        .width(200)
        .onClick(()=>{
          //1.添加任務(wù),就是給任務(wù)數(shù)組中添加一個值
          this.tasks.push(new Task())
          //2.新增任務(wù)后,需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
          this.stat.totalTask = this.tasks.length
        })

      //3.任務(wù)列表
      List({space:5}){
        ForEach(this.tasks,(item:Task, index:number)=>{
          ListItem(){
            Row(){
              //文本
              Text(item.name).fontColor(20)
              //單選框,select決定是否選中,類型布爾值,取Task對象屬性taskStatus
              Checkbox()
                .select(item.taskStatus)
                .onChange((value:boolean)=>{
                  //1.更新當(dāng)前已完成任務(wù)狀態(tài),勾選后修改狀態(tài)為true
                  item.taskStatus = value

                  /*//2.統(tǒng)計已完成的數(shù)量,就是統(tǒng)計數(shù)組中狀態(tài)為true的元素個數(shù)
                  this.finishTask = this.tasks.filter(item=> item.taskStatus).length*/
                  //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
                  this.DataUpdate()
                })
            }
            .width("100%")
            .card()
            .justifyContent(FlexAlign.SpaceBetween)
          }
          /**
           * 用于設(shè)置ListItem的劃出組件。
           * - start: ListItem向右劃動時item左邊的組件(List垂直布局時)或ListItem向下劃動時item上方的組件(List水平布局時)。
           * - end: ListItem向左劃動時item右邊的組件(List垂直布局時)或ListItem向上劃動時item下方的組件(List水平布局時)。
           * - edgeEffect: 滑動效果。
           */
          .swipeAction({end: this.DeleteTaskButton(index)})
        })
      }
      .width("100%")
      .layoutWeight(1) //忽略元素本身尺寸設(shè)置,表示自適應(yīng)占滿剩余空間。
      .alignListItem(ListItemAlign.Center) //ListItem在List交叉軸方向的布局方式(這里就是水平方向居中對齊),默認(rèn)為首部對齊。
    }.width("100%").height("100%")
  }
}

預(yù)覽效果如下:

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

六、@Observed和@objectLink

@objectLink和@observed裝飾器用于在涉及嵌套對象或數(shù)組元素為對象的場景中進(jìn)行雙向數(shù)據(jù)同步

6.1.案例1

以之前的學(xué)生信息展示的基礎(chǔ)案例中,點擊修改學(xué)生寵物年齡的功能和修改寵物列表中寵物信息,修改后無法同步為例,原因在于:

  • 學(xué)生的寵物年齡,是屬于對象的嵌套
  • 寵物列表是屬于數(shù)組中有對象

要解決上面的問題,就需要@Observed和@objectLink裝飾器來實現(xiàn)

1)需要給嵌套的對象和數(shù)組中對象添加@Observed裝飾器,Pet對象屬于嵌套的所以添加裝飾器

class Student{
  sid:number
  name:string
  age:number
  //寵物
  pet:Pet
  constructor(sid:number,name:string,age:number,pet:Pet) {
    this.sid = sid
    this.name = name
    this.age = age
    this.pet = pet
  }
}

@Observed //實現(xiàn)雙向數(shù)據(jù)同步
//寵物
class Pet{
  petName:string
  petAge:number

  constructor(petName:string,petAge:number) {
    this.petName = petName
    this.petAge = petAge
  }
}

2)將需要修改重新渲染的功能抽取出來定義子組件,然后給變量添加@objectLink注解

/**
 * 數(shù)組元素為對象,實現(xiàn)數(shù)據(jù)同步
 */
@Component
struct PetList {
  //子組件的變量必須使用@ObjectLink
  @ObjectLink pet:Pet
  build() {
    Row(){
      Text(`${this.pet.petName}:${this.pet.petAge}`).fontSize(20)
      Button("修改年齡").onClick(()=>{
        //點擊后發(fā)現(xiàn)修改了數(shù)據(jù),但是由于屬性屬于數(shù)組的對象,@State無法讓修改后自動渲染
        this.pet.petAge++
      })
    }.width("100%").justifyContent(FlexAlign.SpaceAround)
  }
}

/**
 * 嵌套對象,實現(xiàn)數(shù)據(jù)同步
 */
@Component
struct PetInfo {
  //子組件的變量必須使用@ObjectLink
  @ObjectLink pet:Pet
  build() {
    //修改Student的屬性是可以的
    Text(`寵物:${this.pet.petName},${this.pet.petAge}`)
      .fontSize(30)
  }
}

注意:其中的對象嵌套,學(xué)生對象里面有個寵物對象,這里在定義的時候,接受的參數(shù)一定是寵物對象

3)調(diào)用定義的子組件

@Entry
@Component
struct StateExample03{
  //私有變量的值是一個對象
  @State s:Student = new Student(2301,"馬保國", 73, new Pet("大黃",3))

  //準(zhǔn)備一個數(shù)組
  @State pets:Pet[] = [new Pet("小白",2300), new Pet("小癡", 1100)]

  build() {
    Column({space:20}){
      /**
       * 數(shù)組元素為對象,實現(xiàn)數(shù)據(jù)同步
       * 調(diào)用PetInfo, 這里的this.s.pet是屬于student對象的pet屬性
       */
      PetInfo({pet:this.s.pet})
        .onClick(()=>{
          //變量通過@State修飾,點擊修改私有變量(點擊一次自增1),然后會自動修改刷新UI
          this.s.pet.petAge++
        })

      //添加寵物
      Button("添加").onClick(()=>{
        this.pets.push(new Pet("小灰"+1, 10))
      })

      Text("---------寵物列表------").fontSize(30).width("100%")
      ForEach(this.pets,(pet:Pet, index)=>{
        /**
         * 嵌套對象,實現(xiàn)數(shù)據(jù)同步
         * 調(diào)用PetList
         */
        PetList({pet:pet})
          .onClick(()=>{
            //變量通過@State修飾,點擊修改私有變量(點擊一次自增1),然后會自動修改刷新UI
            this.s.pet.petAge++
          })
      })

    }
    .width("100%").height("100%")
    .justifyContent(FlexAlign.Center)//主軸方向?qū)R
  }
}
6.1.案例2

還是任務(wù)進(jìn)度列表案例,之前的功能還剩余一部分,當(dāng)任務(wù)完成后,任務(wù)的名稱需要置灰并且出現(xiàn)中劃線,效果如下所示:

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

1)在任務(wù)類上添加裝飾器@Observed

//任務(wù)類
@Observed
class Task{
  static  id:number = 1;
  //任務(wù)名稱,id每次增加1
  name:string = `任務(wù)${Task.id++}`
  //任務(wù)狀態(tài),是否完成
  taskStatus:boolean = false
}

2)在任務(wù)列表中渲染任務(wù)組件功能抽取出來形成子組件,里面使用@ObjectLink裝飾器修飾變量

//任務(wù)列表置灰加下劃線樣式組件
@Extend(Text) function finishedTask(){
  .decoration({type:TextDecorationType.LineThrough}) //LineThrough
  .fontColor("#B1B2B1")
}

/**
 * 這個由于任務(wù)列表里面存放的對象,所以需要使用@objectLink,實現(xiàn)雙向同步,抽取組件
 */
@Component
struct TaskItem {
  //雙向同步數(shù)組中的對象
  @ObjectLink item:Task

  //由于數(shù)據(jù)更新函數(shù),在父組件TaskList,無法移動到這里,所以需要把父組件中的數(shù)據(jù)跟新的函數(shù)DataUpdate(),當(dāng)成參數(shù)傳遞給子組件
  onChangeTask: ()=>void //表示onChangeTask是一個無參返回值為void的函數(shù)

  build() {
    Row(){
      //TODO 判斷是否是完成狀態(tài),如果是完成狀態(tài),則修改為置灰加中劃線
      if(this.item.taskStatus){
        Text(this.item.name).finishedTask() //調(diào)用定義的樣式組件
      }else {
        //文本
        Text(this.item.name).fontColor(20)
      }

      //單選框,select決定是否選中,類型布爾值,取Task對象屬性taskStatus
      Checkbox()
        .select(this.item.taskStatus)
        .onChange((value:boolean)=>{
          //1.更新當(dāng)前已完成任務(wù)狀態(tài),勾選后修改狀態(tài)為true
          this.item.taskStatus = value

          //2.上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
          this.onChangeTask() //更新數(shù)據(jù)方法在父組件,當(dāng)成參數(shù)傳遞到這里,然后調(diào)用
        })
    }
    .width("100%")
    .card()
    .justifyContent(FlexAlign.SpaceBetween)
  }
}

3)在任務(wù)列表組件中調(diào)用上面封裝的子組件?TaskItem,代碼如下:

/**
 * 定義任務(wù)列表子組件
 */
@Component
struct TaskList {
  //TODO 通過@Consume實現(xiàn)雙向同步,調(diào)用組件的時候不需要傳入值,會自動傳入
  @Consume stat: StateInfo

  //保存添加任務(wù)的數(shù)組
  @State tasks: Task[] = []

  //將跟新數(shù)據(jù)的操作進(jìn)一步抽取
  DataUpdate(){
    //需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
    this.stat.totalTask = this.tasks.length
    //跟新已完成任務(wù)總數(shù)
    this.stat.finishTask = this.tasks.filter(item=> item.taskStatus).length
  }

  //自定義刪除刪除
  @Builder DeleteTaskButton(index:number){
    Button(){
      Image($r("app.media.icon_remove_button"))
        .width(20)
        .fillColor("#B0E0E6")
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .onClick(()=>{
      //去數(shù)組中刪除
      this.tasks.splice(index, 1)

      //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
      this.DataUpdate()
    })
    .backgroundColor(Color.Red)
    .margin(10)
  }

  build() {
    Column(){
      //2.添加任務(wù)按鈕
      Button("添加任務(wù)")
        .width(200)
        .onClick(()=>{
          //1.添加任務(wù),就是給任務(wù)數(shù)組中添加一個值
          this.tasks.push(new Task())
          //2.新增任務(wù)后,需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
          this.stat.totalTask = this.tasks.length
        })

      //3.任務(wù)列表
      List({space:5}){
        ForEach(this.tasks,(item:Task, index:number)=>{
          ListItem(){
            //實現(xiàn)數(shù)組中對象數(shù)據(jù)的同步,調(diào)用封裝的子組件
            //this.DataUpdate.bind(this)將函數(shù)當(dāng)成參數(shù)傳遞過去,bind(this)表示使用父組件TaskList的對象,因為更新的數(shù)據(jù)在父組件TaskList中
            TaskItem({item:item, onChangeTask:this.DataUpdate.bind(this)})
          }
          /**
           * 用于設(shè)置ListItem的劃出組件。
           * - start: ListItem向右劃動時item左邊的組件(List垂直布局時)或ListItem向下劃動時item上方的組件(List水平布局時)。
           * - end: ListItem向左劃動時item右邊的組件(List垂直布局時)或ListItem向上劃動時item下方的組件(List水平布局時)。
           * - edgeEffect: 滑動效果。
           */
          .swipeAction({end: this.DeleteTaskButton(index)})
        })
      }
      .width("100%")
      .layoutWeight(1) //忽略元素本身尺寸設(shè)置,表示自適應(yīng)占滿剩余空間。
      .alignListItem(ListItemAlign.Center) //ListItem在List交叉軸方向的布局方式(這里就是水平方向居中對齊),默認(rèn)為首部對齊。
    }.width("100%").height("100%")
  }
}

這里有個新的問題,新定義的子組件TaskItem中沒有數(shù)據(jù)更新的方法DataUpdate,這時候無法更新數(shù)據(jù),而更新數(shù)據(jù)的方法在TaskList中,為了能在子組件中調(diào)用父組件的函數(shù),就需要在組件中定義一個參數(shù)為函數(shù),調(diào)用的時候把數(shù)據(jù)更新方法當(dāng)做函數(shù)傳入即可,語法如下:

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

調(diào)用的時候,數(shù)據(jù)更新的方法DataUpdate,更新的數(shù)據(jù)也在父組件中,所以需要指定是修改的父組件中的數(shù)據(jù)(綁定父組件的this),如下:

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

4)完整的代碼如下:

//任務(wù)類
@Observed
class Task{
  static  id:number = 1;
  //任務(wù)名稱,id每次增加1
  name:string = `任務(wù)${Task.id++}`
  //任務(wù)狀態(tài),是否完成
  taskStatus:boolean = false
}

//統(tǒng)一的卡片樣式
@Styles function  card(){
  .width("90%")
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  //為當(dāng)前組件添加陰影效果
  .shadow({radius:6, color:"1F000000",offsetX:2,offsetY:4})
}

//將統(tǒng)計信息抽取出來形成一個類
class StateInfo{
  //總?cè)蝿?wù)數(shù)量
  totalTask:number
  //已完成數(shù)量
  finishTask:number

  constructor( totalTask:number = 0,finishTask:number = 0 ) {
    this.totalTask = totalTask
    this.finishTask = finishTask
  }
}

@Entry
@Component
struct StatusManagement {
  //TODO 父子組件變量類型是對象, @Prop子組件變量類型是對象的屬性
  //創(chuàng)建統(tǒng)計信息對象
  @Provide stat: StateInfo = new StateInfo()

  build() {
    Column({space:20}){
      //1.任務(wù)進(jìn)度 這里直接調(diào)用自定義的組件,使用的是@Prop,通過屬性傳入
      TaskStatusProgress()

      //2.任務(wù)列表
      //TODO 子組件使用的@Link, 通過$符的方式傳值
      TaskList()
    }
    .size({width:"100%",height:"100%"})
    .backgroundColor("#F0F8FF")
  }
}

/**
 * 定義任務(wù)進(jìn)度組件
 * 使用@Prop裝飾器,監(jiān)控父組件的數(shù)據(jù)狀態(tài),而改變自身的數(shù)據(jù)
 */
@Component
struct TaskStatusProgress {
  //TODO 通過@Consume實現(xiàn)雙向同步,調(diào)用組件的時候不需要傳入值,會自動傳入
  @Consume stat: StateInfo

  build() {
    //1.任務(wù)進(jìn)度
    Row(){
      Text("任務(wù)進(jìn)度:")
        .fontSize(30) //字體大小
        .fontWeight(FontWeight.Bold)//字體加粗

      //環(huán)形和數(shù)字要使用堆疊容器,
      Stack(){
        //環(huán)形組件: 進(jìn)度、總量、樣式
        Progress({value:this.stat.finishTask, total:this.stat.totalTask,type:ProgressType.Ring})
          .width(90)
        Row(){//讓數(shù)字顯示在一起,放在一個容器中
          //任務(wù)完成量
          Text(`${this.stat.finishTask}`)
            .fontSize(25) //字體大小
            .fontColor("#0000CD")

          //任務(wù)總量
          Text(` / ${this.stat.totalTask}`)
            .fontSize(25) //字體大小
        }
      }
    }
    .width("100%")
    .margin({top:20,bottom:20})
    .justifyContent(FlexAlign.SpaceAround) //主軸方向布局
    .card()
  }
}

/**
 * 定義任務(wù)列表子組件
 */
@Component
struct TaskList {
  //TODO 通過@Consume實現(xiàn)雙向同步,調(diào)用組件的時候不需要傳入值,會自動傳入
  @Consume stat: StateInfo

  //保存添加任務(wù)的數(shù)組
  @State tasks: Task[] = []

  //將跟新數(shù)據(jù)的操作進(jìn)一步抽取
  DataUpdate(){
    //需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
    this.stat.totalTask = this.tasks.length
    //跟新已完成任務(wù)總數(shù)
    this.stat.finishTask = this.tasks.filter(item=> item.taskStatus).length
  }

  //自定義刪除刪除
  @Builder DeleteTaskButton(index:number){
    Button(){
      Image($r("app.media.icon_remove_button"))
        .width(20)
        .fillColor("#B0E0E6")
    }
    .width(40)
    .height(40)
    .type(ButtonType.Circle)
    .onClick(()=>{
      //去數(shù)組中刪除
      this.tasks.splice(index, 1)

      //上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
      this.DataUpdate()
    })
    .backgroundColor(Color.Red)
    .margin(10)
  }

  build() {
    Column(){
      //2.添加任務(wù)按鈕
      Button("添加任務(wù)")
        .width(200)
        .onClick(()=>{
          //1.添加任務(wù),就是給任務(wù)數(shù)組中添加一個值
          this.tasks.push(new Task())
          //2.新增任務(wù)后,需要跟新一下任務(wù)總量(就是任務(wù)數(shù)組的長度)
          this.stat.totalTask = this.tasks.length
        })

      //3.任務(wù)列表
      List({space:5}){
        ForEach(this.tasks,(item:Task, index:number)=>{
          ListItem(){
            //實現(xiàn)數(shù)組中對象數(shù)據(jù)的同步,調(diào)用封裝的子組件
            //this.DataUpdate.bind(this)將函數(shù)當(dāng)成參數(shù)傳遞過去,bind(this)表示使用父組件TaskList的對象,因為更新的數(shù)據(jù)在父組件TaskList中
            TaskItem({item:item, onChangeTask:this.DataUpdate.bind(this)})
          }
          /**
           * 用于設(shè)置ListItem的劃出組件。
           * - start: ListItem向右劃動時item左邊的組件(List垂直布局時)或ListItem向下劃動時item上方的組件(List水平布局時)。
           * - end: ListItem向左劃動時item右邊的組件(List垂直布局時)或ListItem向上劃動時item下方的組件(List水平布局時)。
           * - edgeEffect: 滑動效果。
           */
          .swipeAction({end: this.DeleteTaskButton(index)})
        })
      }
      .width("100%")
      .layoutWeight(1) //忽略元素本身尺寸設(shè)置,表示自適應(yīng)占滿剩余空間。
      .alignListItem(ListItemAlign.Center) //ListItem在List交叉軸方向的布局方式(這里就是水平方向居中對齊),默認(rèn)為首部對齊。
    }.width("100%").height("100%")
  }
}

//任務(wù)列表置灰加下劃線樣式組件
@Extend(Text) function finishedTask(){
  .decoration({type:TextDecorationType.LineThrough}) //LineThrough
  .fontColor("#B1B2B1")
}

/**
 * 這個由于任務(wù)列表里面存放的對象,所以需要使用@objectLink,實現(xiàn)雙向同步,抽取組件
 */
@Component
struct TaskItem {
  //雙向同步數(shù)組中的對象
  @ObjectLink item:Task

  //由于數(shù)據(jù)更新函數(shù),在父組件TaskList,無法移動到這里,所以需要把父組件中的數(shù)據(jù)跟新的函數(shù)DataUpdate(),當(dāng)成參數(shù)傳遞給子組件
  onChangeTask: ()=>void //表示onChangeTask是一個無參返回值為void的函數(shù)

  build() {
    Row(){
      //TODO 判斷是否是完成狀態(tài),如果是完成狀態(tài),則修改為置灰加中劃線
      if(this.item.taskStatus){
        Text(this.item.name).finishedTask() //調(diào)用定義的樣式組件
      }else {
        //文本
        Text(this.item.name).fontColor(20)
      }

      //單選框,select決定是否選中,類型布爾值,取Task對象屬性taskStatus
      Checkbox()
        .select(this.item.taskStatus)
        .onChange((value:boolean)=>{
          //1.更新當(dāng)前已完成任務(wù)狀態(tài),勾選后修改狀態(tài)為true
          this.item.taskStatus = value

          //2.上面的更新數(shù)據(jù)進(jìn)一步封裝,然后調(diào)用
          this.onChangeTask() //更新數(shù)據(jù)方法在父組件,當(dāng)成參數(shù)傳遞到這里,然后調(diào)用
        })
    }
    .width("100%")
    .card()
    .justifyContent(FlexAlign.SpaceBetween)
  }
}

鴻蒙全棧開發(fā)全新學(xué)習(xí)指南

也為了積極培養(yǎng)鴻蒙生態(tài)人才,讓大家都能學(xué)習(xí)到鴻蒙開發(fā)最新的技術(shù),針對一些在職人員、0基礎(chǔ)小白、應(yīng)屆生/計算機專業(yè)、鴻蒙愛好者等人群,整理了一套純血版鴻蒙(HarmonyOS Next)全棧開發(fā)技術(shù)的學(xué)習(xí)路線[包含了大APP實戰(zhàn)項目開發(fā)]。

本路線共分為四個階段:

第一階段:鴻蒙初中級開發(fā)必備技能

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

第二階段:鴻蒙南北雙向高工技能基礎(chǔ):https://qr21.cn/Bm8gyp

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

第三階段:應(yīng)用開發(fā)中高級就業(yè)技術(shù)

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

第四階段:全網(wǎng)首發(fā)-工業(yè)級南向設(shè)備開發(fā)就業(yè)技術(shù):https://qr21.cn/Bm8gyp

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

《鴻蒙 (Harmony OS)開發(fā)學(xué)習(xí)手冊》(共計892頁)

如何快速入門?

1.基本概念
2.構(gòu)建第一個ArkTS應(yīng)用
3.……

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

開發(fā)基礎(chǔ)知識:https://qr21.cn/Bm8gyp

1.應(yīng)用基礎(chǔ)知識
2.配置文件
3.應(yīng)用數(shù)據(jù)管理
4.應(yīng)用安全管理
5.應(yīng)用隱私保護(hù)
6.三方應(yīng)用調(diào)用管控機制
7.資源分類與訪問
8.學(xué)習(xí)ArkTS語言
9.……

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

基于ArkTS 開發(fā)

1.Ability開發(fā)
2.UI開發(fā)
3.公共事件與通知
4.窗口管理
5.媒體
6.安全
7.網(wǎng)絡(luò)與鏈接
8.電話服務(wù)
9.數(shù)據(jù)管理
10.后臺任務(wù)(Background Task)管理
11.設(shè)備管理
12.設(shè)備使用信息統(tǒng)計
13.DFX
14.國際化開發(fā)
15.折疊屏系列
16.……

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

鴻蒙開發(fā)面試真題(含參考答案):https://qr21.cn/Bm8gyp

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

鴻蒙入門教學(xué)視頻:

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

美團APP實戰(zhàn)開發(fā)教學(xué):https://qr21.cn/Bm8gyp

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui

寫在最后

  • 如果你覺得這篇內(nèi)容對你還蠻有幫助,我想邀請你幫我三個小忙:
  • 點贊,轉(zhuǎn)發(fā),有你們的 『點贊和評論』,才是我創(chuàng)造的動力。
  • 關(guān)注小編,同時可以期待后續(xù)文章ing??,不定期分享原創(chuàng)知識。
  • 想要獲取更多完整鴻蒙最新學(xué)習(xí)資源,請移步前往小編:https://qr21.cn/FV7h05

HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理,HarmonyOS,OpenHarmony,鴻蒙開發(fā),harmonyos,OpenHarmony,應(yīng)用開發(fā),鴻蒙開發(fā),移動開發(fā),Arkui文章來源地址http://www.zghlxwxcb.cn/news/detail-859747.html

到了這里,關(guān)于HarmonyOS ArkUI實戰(zhàn)開發(fā)—狀態(tài)管理的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • OpenHarmony鴻蒙原生應(yīng)用開發(fā),ArkTS、ArkUI學(xué)習(xí)踩坑學(xué)習(xí)筆記,持續(xù)更新中。

    OpenHarmony鴻蒙原生應(yīng)用開發(fā),ArkTS、ArkUI學(xué)習(xí)踩坑學(xué)習(xí)筆記,持續(xù)更新中。

    結(jié)論:在BIOS里面將Hyper-V打開,DevEco Studio模擬器可以成功啟動。 如果在另外的文件中引用組件,需要使用export導(dǎo)出,并在使用的頁面import該自定義組件。 1.自定義組件(被導(dǎo)入組件) 2.組合組件(引用自定義組件) 1、main_pages.json配置文件配置靜態(tài)路由地址,配置文件

    2024年02月04日
    瀏覽(21)
  • HarmonyOS 鴻蒙開發(fā)DevEco Studio OpenHarmony:創(chuàng)建OpenHarmony工程

    目錄 創(chuàng)建和配置新工程 將原子化服務(wù)工程改為應(yīng)用工程 當(dāng)開始開發(fā)一個OpenHarmony應(yīng)用/服務(wù)時,首先需要根據(jù)工程創(chuàng)建向?qū)?,?chuàng)建一個新的工程,工具會自動生成對應(yīng)的代碼和資源模板。 說明 在運行DevEco Studio工程時,建議每一個運行窗口有2GB以上的可用內(nèi)存空間。 通過如下

    2024年01月25日
    瀏覽(22)
  • 鴻蒙應(yīng)用開發(fā)學(xué)習(xí)路線(OpenHarmony/HarmonyOS)

    鴻蒙應(yīng)用開發(fā)學(xué)習(xí)路線(OpenHarmony/HarmonyOS)

    作者:堅果 團隊:堅果派 公眾號:“大前端之旅” 潤開鴻技術(shù)專家,華為HDE,InfoQ簽約作者,OpenHarmony布道師,擅長HarmonyOS應(yīng)用開發(fā)、熟悉服務(wù)卡片開發(fā),在“戰(zhàn)碼先鋒”活動中作為大隊長,累計培養(yǎng)三個小隊長,帶領(lǐng)100+隊員完成Pr的提交合入。 歡迎通過主頁或者私信聯(lián)系

    2024年02月15日
    瀏覽(97)
  • OpenHarmony開發(fā)實戰(zhàn):ArkUI常用布局容器對齊方式(ArkTS

    OpenHarmony開發(fā)實戰(zhàn):ArkUI常用布局容器對齊方式(ArkTS

    export struct ColumnShowList { @Consume currentColumnJustifyContent: FlexAlign; @Consume currentColumnAlignItems: HorizontalAlign; build() { Column() { Column() { ForEach(LIST, (item: number) = { CommonItem({ item: item }) }, (item: number) = JSON.stringify(item)) } … // 設(shè)置主軸對齊方式 ColumnMainAlignRadioList() .margin({ top: MARGIN_FONT_SIZE_SP

    2024年04月14日
    瀏覽(29)
  • HarmonyOS 鴻蒙開發(fā)DevEco Studio OpenHarmony:配置開發(fā)環(huán)境

    目錄 下載OpenHarmony SDK及工具鏈 參考信息 配置DevEco Studio代理 配置NPM代理 在進(jìn)行OpenHarmony應(yīng)用/服務(wù)開發(fā)前,需要提前在DevEco Studio中下載對應(yīng)版本的SDK。下載OpenHarmony SDK需要連接網(wǎng)絡(luò),一般情況下,可以直接下載;但部分用戶的網(wǎng)絡(luò)可能受限,此時需要先根據(jù)參考信息 配置相

    2024年02月19日
    瀏覽(93)
  • HarmonyOS 鴻蒙開發(fā)DevEco Studio OpenHarmony:使用低代碼進(jìn)行開發(fā)

    HarmonyOS 鴻蒙開發(fā)DevEco Studio OpenHarmony:使用低代碼進(jìn)行開發(fā)

    OpenHarmony低代碼開發(fā)方式,具有豐富的UI界面編輯功能,遵循JS、TS開發(fā)規(guī)范 ,通過可視化界面開發(fā)方式快速構(gòu)建布局,可有效降低用戶的時間成本和提升用戶構(gòu)建UI界面的效率。 說明 支持使用低代碼進(jìn)行JS/eTS頁面開發(fā),本章節(jié)以開發(fā)eTS頁面為例,介紹低代碼功能及使用方法。

    2024年02月19日
    瀏覽(89)
  • HarmonyOS 鴻蒙開發(fā)DevEco Studio OpenHarmony:編譯構(gòu)建概述

    目錄 OpenHarmony構(gòu)建體系 構(gòu)建工具Hvigor 構(gòu)建插件hvigor-ohos-plugin 工程目錄及配置文件說明 如何構(gòu)建應(yīng)用/服務(wù) 啟動應(yīng)用/服務(wù)構(gòu)建 查看編譯過程

    2024年02月22日
    瀏覽(93)
  • HarmonyOS ArkUI實戰(zhàn)開發(fā)-NAPI 加載原理(下)

    HarmonyOS ArkUI實戰(zhàn)開發(fā)-NAPI 加載原理(下)

    上一節(jié)筆者給大家講解了 JS 引擎解釋執(zhí)行到? import ?語句的加載流程,總結(jié)起來就是利用? dlopen() ?方法的加載特性向? NativeModuleManager ?內(nèi)部的鏈接尾部添加一個? NativeModule ,沒有閱讀過上節(jié)文章的小伙伴,筆者強烈建議閱讀一下,本節(jié)筆者繼續(xù)給大家講解 JS 調(diào)用 C++ 方法

    2024年04月27日
    瀏覽(24)
  • 鴻蒙開發(fā)實戰(zhàn)-(ArkUI)List組件和Grid組件的使用

    鴻蒙開發(fā)實戰(zhàn)-(ArkUI)List組件和Grid組件的使用

    在我們常用的手機應(yīng)用中,經(jīng)常會見到一些數(shù)據(jù)列表,如設(shè)置頁面、通訊錄、商品列表等。下圖中兩個頁面都包含列表,“首頁”頁面中包含兩個網(wǎng)格布局,“商城”頁面中包含一個商品列表。 上圖中的列表中都包含一系列相同寬度的列表項,連續(xù)、多行呈現(xiàn)同類數(shù)據(jù),例如

    2024年01月22日
    瀏覽(26)
  • 鴻蒙開發(fā)實戰(zhàn)-OpenHarmony沙箱文件

    鴻蒙開發(fā)實戰(zhàn)-OpenHarmony沙箱文件

    在openharmony文件管理模塊中,按文件所有者分類分為應(yīng)用文件和用戶文件和系統(tǒng)文件。 1)沙箱文件。也叫做應(yīng)用文件,包括應(yīng)用安裝文件、應(yīng)用資源文件、應(yīng)用緩存文件 在使用時首先需要導(dǎo)入包 import fs from “@ohos.file.fs”; 在API9之前使用“@ohos.fileio”,API9之后廢棄。 1.常用

    2024年01月19日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包