掘金 人工智能 05月09日 14:45
一文搞清楚HarmonyOS NEXT中状态管理 V1 版本:父子组件数据传递装饰器的奇妙之旅
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入浅出地介绍了在HarmonyOS NEXT开发中,父子组件之间数据传递的两种主要方式:@Prop和@Link。@Prop用于单向数据传递,父组件向子组件传递数据,子组件的修改不会影响父组件。@Link则实现了双向数据绑定,父组件和子组件共享数据,任何一方的修改都会立即反映到另一方。文章通过生动的比喻和示例代码,详细讲解了这两种方式的特性、适用场景以及浅拷贝和深拷贝的概念,旨在帮助开发者更好地理解和运用这两种数据传递方式,构建更强大、更稳固的HarmonyOS应用。

📦`@Prop`:单向数据传递,父组件向子组件传递数据,子组件接收后可使用,但对数据的修改不会反馈给父组件,类似于快递员单向送货。

🔗`@Link`:双向数据绑定,父组件与子组件共享同一份数据,任何一方修改都会立即同步到另一方,如同心灵感应的双胞胎。

📚浅拷贝与深拷贝:浅拷贝只复制引用,深拷贝则创建全新的独立副本,理解它们对于处理对象和数组等引用类型的数据传递至关重要,避免意外的数据修改。

程序员Feri一名12年+的程序员,做过开发带过团队创过业,擅长Java、嵌入式、鸿蒙、人工智能等,专注于程序员成长那点儿事,希望在成长的路上有你相伴!君志所向,一往无前!


状态管理 V1 版本:父子组件数据传递装饰器的奇妙之旅

在HarmonyOS NEXT开发的奇妙世界里,组件就像是一个个独立的小王国,它们各自有着自己的职责和功能。但是,这些小王国之间并不是孤立存在的,它们需要相互交流、相互协作,才能构建出一个完整而强大的应用帝国。

而在这个过程中,数据传递就像是王国之间的信使,负责在不同的组件之间传递信息。

在状态管理的 V1 版本中,我们有两位强大的信使:@Prop@Link。它们各自有着独特的能力,能够帮助我们实现父子组件之间的数据传递。接下来,让我们一起踏上这场奇妙的旅程,探索它们的奥秘吧!

1. @Prop:单向传递的快递员

1.1 基本概念

想象一下,有一个快递员叫 @Prop,他负责从一个王国(父组件)向另一个王国(子组件)传递包裹(数据)。

这个快递员有一个特殊的规则:他只负责把包裹从父组件送到子组件,而子组件对包裹所做的任何修改,他都不会带回给父组件。

1.2 装饰器参数

@Prop 就像是一个不需要任何证件的快递员,他不需要任何参数就能工作。

1.3 同步类型

单向同步。这就好比父组件是包裹的发送者,子组件是包裹的接收者。

发送者可以随时发送新的包裹,接收者会收到最新的包裹内容。但是,接收者对包裹所做的任何修改,发送者都不会知道。

1.4 允许装饰的变量类型

@Prop 这个快递员非常能干,几乎什么类型的包裹都能送。

他可以送 Objectclassstringnumberbooleanenum 类型的包裹,甚至还可以送这些类型的数组包裹。

1.5 被装饰变量的初始值

@Prop 允许子组件在收到包裹之前,先给自己准备一个初始的包裹内容。但是,一旦收到父组件的包裹,这个初始内容就会被父组件的包裹内容覆盖。

1.6 示例代码

下面是一个有趣的示例,展示了 @Prop 的使用:

doubaocanvas

// 子组件:魔法按钮@Componentexport struct MagicButton {  // 魔法按钮的图标库  magicIcons: Resource[] = [    $r("sys.media.star"),    $r("sys.media.moon"),    $r("sys.media.sun")  ];    // 按钮的当前状态  @State currentState: number = 0;    // 按钮的名称,由父组件传递  @Prop buttonName: string = "普通按钮";  build() {    Column() {      // 显示当前的魔法图标      Image(this.magicIcons[this.currentState])        .width(100)        .height(100)        .animation({ duration: 500, curve: "ease-in-out" });            // 魔法按钮      Button(this.buttonName)        .onClick(() => {          // 切换魔法状态          this.currentState = (this.currentState + 1) % 3;                    // 尝试修改按钮名称,但这不会影响父组件          this.buttonName = `魔法状态${this.currentState}`;          console.log(`子组件将按钮名称改为:${this.buttonName}`);        })        .width(150)        .height(50)        .backgroundColor("#6200EA")        .fontColor(Color.White)        .borderRadius(25);    }    .width("100%")    .height("100%")    .justifyContent(FlexAlign.Center);  }}// 父组件:魔法控制中心@Entry@Componentstruct MagicControlCenter {  // 控制中心的状态  @State magicWord: string = "魔法";    build() {    Column() {      // 输入魔法词      TextInput({ placeholder: "输入魔法词..." })        .onChange(v => {          this.magicWord = v;          console.log(`父组件设置魔法词为:${this.magicWord}`);        })        .width("80%")        .margin({ top: 50 })        .backgroundColor("#E0E0E0")        .borderRadius(10)        .padding(10);            // 显示当前魔法词      Text(`当前魔法词:${this.magicWord}`)        .fontSize(18)        .margin({ top: 20 });            // 使用魔法按钮      MagicButton({ buttonName: this.magicWord })        .margin({ top: 50 });    }    .width("100%")    .height("100%")    .padding(20);  }}

1.7 代码解释

在这个魔法世界的示例中,我们有一个魔法控制中心(父组件)和一个魔法按钮(子组件)。控制中心可以通过输入框设置魔法词,然后将这个魔法词作为 buttonName 属性传递给魔法按钮。

当我们在控制中心输入新的魔法词时,魔法按钮会立即更新显示新的名称。但是,当我们点击魔法按钮时,虽然按钮内部会尝试修改 buttonName,但这个修改不会影响到控制中心的 magicWord。这就好比魔法按钮只是在自己的小世界里改变了按钮名称的副本,而真正的魔法词仍然掌握在控制中心手中。

2. @Link:心灵感应的双胞胎

2.1 基本概念

现在,让我们认识另一位神奇的信使 @Link。他就像是一对心灵感应的双胞胎,无论相隔多远,其中一个的想法和感受都会立即被另一个感知到。

在组件的世界里,@Link 可以让父组件和子组件共享同一个数据,任何一方对数据的修改都会立即反映到另一方。

2.2 装饰器参数

@Link 就像一对不需要任何介绍的双胞胎,他们之间的心灵感应是天生的,不需要任何参数来建立联系。

2.3 同步类型

双向同步。这意味着父组件和子组件就像双胞胎一样,任何一方对共享数据的修改都会立即被另一方感知到。

2.4 允许装饰的变量类型

@Link 这对双胞胎非常包容,几乎可以共享任何类型的数据。

他们可以共享 Objectclassstringnumberbooleanenum 类型的数据,甚至还可以共享这些类型的数组和 Date 类型的数据。

2.5 被装饰变量的初始值

@Link 这对双胞胎必须从同一个源头获得他们的初始数据,因此子组件不能自己初始化 @Link 装饰的变量,必须由父组件提供初始值。

2.6 示例代码

下面是一个有趣的示例,展示了 @Link 的使用:

doubaocanvas

// 子组件:能量水晶@Componentexport struct EnergyCrystal {  // 水晶的不同形态  crystalForms: Resource[] = [    $r("sys.media.crystal_blue"),    $r("sys.media.crystal_green"),    $r("sys.media.crystal_purple")  ];    // 水晶的当前状态  @State currentForm: number = 0;    // 能量值,与父组件双向绑定  @Link energyLevel: number;    // 上次点击时间,用于防止双击  @State lastClickTime: number = 0;  build() {    Column() {      // 显示当前水晶形态      Image(this.crystalForms[this.currentForm])        .width(150)        .height(150)        .animation({ duration: 500, curve: "spring" });            // 显示当前能量值      Text(`能量值:${this.energyLevel}`)        .fontSize(20)        .fontWeight(FontWeight.Bold)        .margin({ top: 20 })        .fontColor(this.getEnergyColor());            // 点击水晶增加能量      GestureDetector({        child: Container()          .width(150)          .height(150)          .backgroundColor("#00000000")      })      .onClick(() => {        const now = Date.now();        // 防止双击        if (now - this.lastClickTime > 300) {          this.lastClickTime = now;                    // 增加能量值          this.energyLevel += 10;                    // 根据能量值改变水晶形态          this.currentForm = Math.floor(this.energyLevel / 100) % 3;                    // 播放能量增加动画          this.playEnergyAnimation();        }      });    }    .width("100%")    .height("100%")    .justifyContent(FlexAlign.Center);  }    // 根据能量值获取颜色  getEnergyColor() {    if (this.energyLevel < 50) return Color.Red;    if (this.energyLevel < 100) return Color.Orange;    return Color.Green;  }    // 播放能量增加动画  playEnergyAnimation() {    // 这里可以添加更复杂的动画效果    console.log("能量增加动画播放");  }}// 父组件:能量监控站@Entry@Componentstruct EnergyMonitoringStation {  // 总能量值  @State totalEnergy: number = 0;    // 能量收集器数量  @State collectorCount: number = 1;    build() {    Column() {      // 显示总能量      Text(`总能量:${this.totalEnergy}`)        .fontSize(24)        .fontWeight(FontWeight.Bold)        .margin({ top: 30 });            // 能量收集器控制      Row() {        Text("能量收集器数量:")          .fontSize(18);                Button("-")          .onClick(() => {            if (this.collectorCount > 1) {              this.collectorCount--;            }          })          .width(40)          .height(40)          .backgroundColor("#B71C1C")          .fontColor(Color.White)          .margin({ left: 20 });                Text(`${this.collectorCount}`)          .fontSize(18)          .margin({ left: 10, right: 10 });                Button("+")          .onClick(() => {            if (this.collectorCount < 3) {              this.collectorCount++;            }          })          .width(40)          .height(40)          .backgroundColor("#2E7D32")          .fontColor(Color.White);      }      .margin({ top: 20 });            // 显示能量收集器      ForEach(Array(this.collectorCount).fill(0), (_, index) => {        EnergyCrystal({ energyLevel: this.totalEnergy })          .margin({ top: 30 });      });            // 全局能量控制      Button("重置能量")        .onClick(() => {          this.totalEnergy = 0;        })        .width("80%")        .height(50)        .backgroundColor("#1A237E")        .fontColor(Color.White)        .margin({ top: 50 })        .borderRadius(25);    }    .width("100%")    .height("100%")    .padding(20);  }}

2.7 代码解释

在这个能量世界的示例中,我们有一个能量监控站(父组件)和一个或多个能量水晶(子组件)。

监控站负责监控总能量值,而能量水晶则负责收集能量。

当我们点击能量水晶时,水晶的能量值会增加。由于能量值是通过 @Link 与父组件双向绑定的,所以父组件的总能量值也会立即增加。

同样地,当我们在父组件中重置能量值时,所有子组件的能量值也会立即更新。

这就好比能量监控站和能量水晶是一对心灵感应的双胞胎,无论哪一方的能量发生变化,另一方都能立即感知到并做出相应的反应。

3. 浅拷贝和深拷贝的奇妙比喻

在我们的数据传递旅程中,还有两个重要的概念需要理解:浅拷贝和深拷贝。

让我们用一个有趣的比喻来解释它们。

假设你有一本非常珍贵的魔法书,里面有许多强大的咒语。浅拷贝就像是给这本书拍了一张照片,照片上的咒语看起来和原书一模一样,但实际上只是一个图像,如果你试图在照片上修改咒语,是不会有任何效果的。

而深拷贝则像是完全复制了一本魔法书,包括书中的每一个字、每一个魔法符号。这两本书是完全独立的,你可以在其中一本上随意修改咒语,而不会影响另一本。

@Prop@Link 的使用中,如果传递的是引用类型的数据(如对象或数组),就需要注意是使用浅拷贝还是深拷贝,以避免意外的数据修改。

4. 总结

在这场奇妙的旅程中,我们认识了两位强大的信使:@Prop@Link@Prop 就像是一个单向传递的快递员,负责将数据从父组件传递到子组件,但不会将子组件的修改带回给父组件。

@Link 则像是一对心灵感应的双胞胎,让父组件和子组件能够共享数据,任何一方的修改都会立即被另一方感知到。

通过这两位信使,我们可以在组件之间建立起高效、可靠的数据传递通道,让我们的应用帝国更加稳固和强大。

希望通过这个生动有趣的比喻,你对 @Prop@Link 有了更深入的理解。在你的HarmonyOS NEXT开发旅程中,好好利用这两位信使,创造出更加精彩的应用吧!

好啦,本篇就到这里啦,加油哟!关注我,跟我一起成长哈!

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

@Prop @Link HarmonyOS NEXT 数据传递 组件通信
相关文章