HarmonyOS的父子组件如何传递数组类的值?

阅读 763
avatarAI BotBETA

在HarmonyOS中,父子组件之间传递数组类型的值可以通过属性(Property)和事件(Event)机制来实现。以下是具体的方法:

方法一:通过属性(Property)传递数组

  1. 父组件定义数组并传递给子组件

    在父组件的 .hml 文件中,通过属性将数组传递给子组件:

    <!-- ParentComponent.hml -->
    <div>
        <ChildComponent array="{{parentArray}}"/>
    </div>

在父组件的 .js 文件中,定义数组:

// ParentComponent.js
export default {
    data: {
        parentArray: [1, 2, 3, 4, 5]
    }
}
  1. 子组件接收数组

    在子组件的 .js 文件中,通过 props 接收数组:

    // ChildComponent.js
    export default {
        props: {
            array: Array
        }
    }

在子组件的 .hml.js 文件中,可以使用接收到的数组:

// 例如,在 ChildComponent.js 中打印数组
export default {
    props: {
        array: Array
    },
    onInit() {
        console.log(this.array); // 输出: [1, 2, 3, 4, 5]
    }
}

方法二:通过事件(Event)传递数组(通常用于子组件向父组件传递数据)

虽然事件机制主要用于子组件向父组件发送消息,但也可以间接用于父组件向子组件发送复杂数据(如数组),不过这种方式相对复杂且不推荐。通常,更直接的方法是使用属性传递。

不过,为了完整性,这里简要说明如何通过事件机制(通常用于子组件向父组件发送消息)结合局部状态管理来实现数据传递:

  1. 父组件监听子组件的事件

    在父组件的 .hml 文件中,监听子组件的事件:

    <!-- ParentComponent.hml -->
    <div>
        <ChildComponent @sendArray="handleArray"/>
    </div>

在父组件的 .js 文件中,定义事件处理函数:

// ParentComponent.js
export default {
    data: {
        receivedArray: []
    },
    handleArray(e) {
        this.receivedArray = e.detail.array;
    }
}
  1. 子组件触发事件并传递数组

    在子组件的 .js 文件中,触发事件并传递数组:

    // ChildComponent.js
    export default {
        data: {
            localArray: [6, 7, 8, 9, 10]
        },
        someFunction() {
            this.$emit('sendArray', { array: this.localArray });
        }
    }

注意:在HarmonyOS开发中,更常见且推荐的方式是使用属性机制来传递数组类型的值,因为这种方式更直接且易于管理。事件机制通常用于处理用户交互和子组件向父组件发送消息的场景。

1 个回答

@Prop装饰的变量和父组件建立单向的同步关系:

@Prop变量允许在本地修改,但修改后的变化不会同步回父组件。

当数据源更改时,@Prop装饰的变量都会更新,并且会覆盖本地所有更改。因此,数值的同步是父组件到子组件(所属组件),子组件数值的变化不会同步到父组件。

父组件@State数组项到子组件@Prop简单数据类型同步

父组件中@State如果装饰的数组,其数组项也可以初始化@Prop。以下示例中父组件Index中@State装饰的数组arr,将其数组项初始化子组件Child中@Prop装饰的value。

@Component
struct Child {
  @Prop value: number = 0;

  build() {
    Text(`${this.value}`)
      .fontSize(50)
      .onClick(() => {
        this.value++
      })
  }
}

@Entry
@Component
struct Index {
  @State arr: number[] = [1, 2, 3];

  build() {
    Row() {
      Column() {
        Child({ value: this.arr[0] })
        Child({ value: this.arr[1] })
        Child({ value: this.arr[2] })

        Divider().height(5)

        ForEach(this.arr,
          (item: number) => {
            Child({ value: item })
          },
          (item: number) => item.toString()
        )
        Text('replace entire arr')
          .fontSize(50)
          .onClick(() => {
            // 两个数组都包含项“3”。
            this.arr = this.arr[0] == 1 ? [3, 4, 5] : [1, 2, 3];
          })
      }
    }
  }
}

初始渲染创建6个子组件实例,每个@Prop装饰的变量初始化都在本地拷贝了一份数组项。子组件onclick事件处理程序会更改局部变量值。

如果点击界面上的“1”六下,“2”五下、“3”四下,将所有变量的本地取值都变为“7”。

7
7
7
----
7
7
7

单击replace entire arr后,屏幕将显示以下信息。

3
4
5
----
7
4
5
  • 在子组件Child中做的所有的修改都不会同步回父组件Index组件,所以即使6个组件显示都为7,但在父组件Index中,this.arr保存的值依旧是[1,2,3]。
  • 点击replace entire arr,this.arr[0] == 1成立,将this.arr赋值为[3, 4, 5];
  • 因为this.arr[0]已更改,Child({value: this.arr[0]})组件将this.arr[0]更新同步到实例@Prop装饰的变量。Child({value: this.arr[1]})和Child({value: this.arr[2]})的情况也类似。
  • this.arr的更改触发ForEach更新,this.arr更新的前后都有数值为3的数组项:[3, 4, 5] 和[1, 2, 3]。根据diff算法,数组项“3”将被保留,删除“1”和“2”的数组项,添加为“4”和“5”的数组项。这就意味着,数组项“3”的组件不会重新生成,而是将其移动到第一位。所以“3”对应的组件不会更新,此时“3”对应的组件数值为“7”,ForEach最终的渲染结果是“7”,“4”,“5”。

本文参与了 【 HarmonyOS NEXT 技术问答冲榜,等你来战!】欢迎正在阅读的你也加入。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题