ArkTS中如何实现组件间通信

2025-06发布2次浏览

在ArkTS(HarmonyOS的TypeScript开发框架)中,组件间通信是构建复杂用户界面时一个非常重要的主题。组件间通信可以分为父子组件通信、兄弟组件通信以及跨层级组件通信等几种类型。下面我们将详细探讨每种类型的实现方式,并提供代码示例。


1. 父子组件通信

1.1 父组件向子组件传递数据

父组件可以通过props将数据传递给子组件。子组件通过定义props接口来接收这些数据。

代码示例:

// 子组件 ChildComponent.ts
import { Component, Prop } from '@arkui/arkts';

@Component
export default class ChildComponent extends ArkObject {
  @Prop() message: string;

  render() {
    return (
      <div>{this.message}</div>
    );
  }
}

// 父组件 ParentComponent.ts
import { Component } from '@arkui/arkts';
import ChildComponent from './ChildComponent';

@Component
export default class ParentComponent extends ArkObject {
  private parentMessage = 'Hello from Parent!';

  render() {
    return (
      <div>
        <ChildComponent message={this.parentMessage} />
      </div>
    );
  }
}

1.2 子组件向父组件传递数据

子组件可以通过事件触发的方式将数据传递给父组件。父组件通过监听子组件的事件来获取数据。

代码示例:

// 子组件 ChildComponent.ts
import { Component, Prop, Emit } from '@arkui/arkts';

@Component
export default class ChildComponent extends ArkObject {
  @Prop() initialCount: number;
  @Emit('countUpdated') emitCountUpdated(newCount: number) {}

  private updateCount() {
    const newCount = this.initialCount + 1;
    this.emitCountUpdated(newCount);
  }

  render() {
    return (
      <button onClick={() => this.updateCount()}>Increase Count</button>
    );
  }
}

// 父组件 ParentComponent.ts
import { Component } from '@arkui/arkts';
import ChildComponent from './ChildComponent';

@Component
export default class ParentComponent extends ArkObject {
  private count = 0;

  onCountUpdated(newCount: number) {
    this.count = newCount;
  }

  render() {
    return (
      <div>
        <p>Current Count: {this.count}</p>
        <ChildComponent initialCount={this.count} countUpdated={(newCount) => this.onCountUpdated(newCount)} />
      </div>
    );
  }
}

2. 兄弟组件通信

兄弟组件之间不能直接通信,通常需要借助父组件作为中介。父组件通过props和事件监听的方式,将数据从一个兄弟组件传递到另一个兄弟组件。

代码示例:

// 父组件 ParentComponent.ts
import { Component } from '@arkui/arkts';
import SiblingA from './SiblingA';
import SiblingB from './SiblingB';

@Component
export default class ParentComponent extends ArkObject {
  private sharedData = '';

  onSharedDataChanged(newData: string) {
    this.sharedData = newData;
  }

  render() {
    return (
      <div>
        <SiblingA onDataChanged={(data) => this.onSharedDataChanged(data)} />
        <SiblingB sharedData={this.sharedData} />
      </div>
    );
  }
}

// 兄弟组件 A (SiblingA.ts)
import { Component, Emit } from '@arkui/arkts';

@Component
export default class SiblingA extends ArkObject {
  @Emit('dataChanged') emitDataChanged(data: string) {}

  private sendData() {
    this.emitDataChanged('Data from Sibling A');
  }

  render() {
    return (
      <button onClick={() => this.sendData()}>Send Data to Sibling B</button>
    );
  }
}

// 兄弟组件 B (SiblingB.ts)
import { Component, Prop } from '@arkui/arkts';

@Component
export default class SiblingB extends ArkObject {
  @Prop() sharedData: string;

  render() {
    return (
      <div>Received Data: {this.sharedData}</div>
    );
  }
}

3. 跨层级组件通信

对于跨层级组件通信,推荐使用状态管理工具或事件总线(Event Bus)。以下是一个简单的事件总线实现。

3.1 实现事件总线

// EventBus.ts
class EventBus {
  private static instance: EventBus;
  private events: Record<string, Array<(data: any) => void>> = {};

  private constructor() {}

  public static getInstance(): EventBus {
    if (!EventBus.instance) {
      EventBus.instance = new EventBus();
    }
    return EventBus.instance;
  }

  public $on(event: string, callback: (data: any) => void): void {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(callback);
  }

  public $emit(event: string, data?: any): void {
    if (this.events[event]) {
      this.events[event].forEach((callback) => callback(data));
    }
  }

  public $off(event: string, callback?: (data: any) => void): void {
    if (callback && this.events[event]) {
      this.events[event] = this.events[event].filter((cb) => cb !== callback);
    } else {
      delete this.events[event];
    }
  }
}

export default EventBus.getInstance();

3.2 使用事件总线进行跨层级通信

// 组件 A 发送事件
import EventBus from './EventBus';

function sendEvent() {
  EventBus.$emit('customEvent', 'Data from Component A');
}

// 组件 B 接收事件
import EventBus from './EventBus';

function setupEventListener() {
  EventBus.$on('customEvent', (data) => {
    console.log('Received:', data); // 输出 "Data from Component A"
  });
}

4. 总结与扩展

  • 父子组件通信:通过props和事件机制实现。
  • 兄弟组件通信:通过父组件作为中介。
  • 跨层级组件通信:推荐使用事件总线或状态管理工具。

如果项目复杂度较高,建议引入状态管理工具(如Pinia或Redux),以更好地管理和同步全局状态。