如何实现子组件数据传递给父组件且父组件修改数据不影响子组件
=============================

#### 问题现象

父子组件均设置状态变量（如selectedData: string\[\]），如何实现在子组件数据变化时，数据传递给父组件，在父组件对数据进行修改处理时，修改后的数据不会传递给子组件。

#### 背景知识

[Emitter模块](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-emitter)提供了在同一进程不同线程间或同一线程内发送和处理事件的能力，可以通过[emitter.emit](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-emitter#emitteremit)接口发送指定事件。

#### 解决方案

可以使用Emitter模块的emit接口，EventData定义事件携带的数据，将子组件的数据发送给父组件，父组件调用emitter.on函数接收事件携带的数据，实现父子组件之间实现数据通信，且在父组件处理数据时不会影响子组件的数据。

1.  子组件修改数据，定义事件携带数据并发送事件。
    
    _//_ _修改子组件数据_
    this.selectedData.push(data);
    let eventDataMap \= new Map<string, Object\>();
    eventDataMap.set("content", data);
    _//_ _定义事件携带的数据_
    let eventData: emitter.EventData \= {
      data: {
        eventDataMap
      }
    };
    _//_ _设置事件优先级_
    let options: emitter.Options \= {
      priority: emitter.EventPriority.HIGH
    };
    _//_ _发送eventId为EmitterTest事件_
    emitter.emit("EmitterTest", options, eventData);
    
2.  父组件接收事件，执行回调函数，获取子组件数据。
    
    _//_ _收到eventId为EmitterTest的事件后执行回调函数_
    emitter.on('EmitterTest', (eventData: emitter.EventData) \=\> {
      let eventDataMap \= eventData.data?.eventDataMap as Map<string, Object\>;
      this.selectedData.push(eventDataMap.get('content') as string);
      console.info(\`EmitterTest callback, eventData: ${eventDataMap.get('content')}\`);
    });
    
3.  父组件按照业务需要修改数据，如删除数据。
    
    _//_ _删除数据内第一个元素_
    this.selectedData.splice(0, 1);
    

完整示例代码如下：

import { emitter } from '@kit.BasicServicesKit';

_//_ _定义子组件_
@Component
struct ChildComponent {
  @State selectedData: string\[\] \= \[\];

  build() {
    Column() {
      Text('修改子组件数据')
        .fontSize(16)
        .fontWeight(FontWeight.Bold)
        .onClick(() \=\> {
          let data \= new Date().toString();
          _// 修改子组件数据_
          this.selectedData.push(data);
          let eventDataMap \= new Map<string, Object\>();
          eventDataMap.set("content", data);
         _ // 定义事件携带的数据_
          let eventData: emitter.EventData \= {
            data: {
              eventDataMap
            }
          };
         _ // 设置事件优先级_
          let options: emitter.Options \= {
            priority: emitter.EventPriority.HIGH
          };
          _//_ _发送eventId为EmitterTest事件_
          emitter.emit("EmitterTest", options, eventData);
        });
      ForEach(this.selectedData, (item: string) \=\> {
        Text(item);
      });
    }
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center);
  }
}

@Entry
@Component
struct ParentComponent {
  @State selectedData: string\[\] \= \[\];

  aboutToAppear(): void {
   _ // 收到eventId为EmitterTest的事件后执行回调函数_
    emitter.on('EmitterTest', (eventData: emitter.EventData) \=\> {
      let eventDataMap \= eventData.data?.eventDataMap as Map<string, Object\>;
      this.selectedData.push(eventDataMap.get('content') as string);
      console.info(\`EmitterTest callback, eventData: ${eventDataMap.get('content')}\`);
    });
  }

  build() {
    Column({ space: 10 }) {
      Column() {
        ForEach(this.selectedData, (item: string) \=\> {
          Text(item);
        });
        Text('删除父组件数据')
          .onClick(() \=\> {
            _// 删除数据内第一个元素_
            this.selectedData.splice(0, 1);
          });
      }
      .justifyContent(FlexAlign.End)
      .width('100%')
      .height('50%');

      Text('---------------分割线\--------------')
        .width('100%')
        .textAlign(TextAlign.Center);

      ChildComponent()
        .layoutWeight(1);
    }
    .height('100%')
    .width('100%');
  }
}