> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/contributor/contributor-zh/gong-xian-zhe-zhi-nan/yi-zhi-zu-jian/components.md).

# 组件

组件是自包含的软件片段，被设计成黑盒：它们接收其他组件（或不接收任何组件）来完成自身任务。其主要目标是解耦代码段并最大化可测试性。

## 目录结构

所有组件 MUST 定义在一个专用目录中，该目录至少包含以下四个文件：

* `component.ts` - 包含组件的实现代码
* `types.ts` - 包含组件的接口和公开类型
* `errors.ts` - 包含所有导出的错误类
* `index.ts` - 导出组件的公共 API

### 示例结构

```
src/
└── components/
    └── my-component/
        ├── component.ts
        ├── types.ts
        ├── errors.ts
        └── index.ts
```

## 类型文件

组件遵循一个定义其公共 API 的接口。该接口可在可互换的组件之间共享，或用于了解组件公开的方法。

所有具有自己接口的组件 MUST 将其定义在组件目录中的一个 `types.ts` 文件里。

组件公开的其他类型也 MUST 放在此文件中。

### 示例： `types.ts`

```tsx
export type Something = {
  aValue: boolean
  anotherValue: string
}

export interface IMyComponent {
  myFunction: () => boolean
  getSomething: () => Something
}
```

### 共享类型

多个组件之间共享的类型，例如通用接口，MUST 放在项目源代码根目录中的一个 `types.ts` 文件中（`/src/types.ts`).

## 组件文件

组件文件包含组件创建者函数。该函数遵循特定的命名和结构约定。

### 命名约定

组件创建者函数 MUST 命名为： `create` + `组件名称` + `Component`

**示例：** `createMyNewComponent`

### 函数签名

创建者函数 MUST：

1. 接收一个 components 对象作为第一个参数，其中包含所有依赖项
2. 可选地接收额外的配置参数
3. 返回一个包含公开（公共）方法的对象

### 组件结构

在组件创建者函数开始时：

1. 从 components 对象中提取依赖项
2. 初始化通用变量（例如日志记录器、配置）
3. 定义内部辅助函数
4. 定义公共方法
5. 返回公共 API

### 示例： `component.ts`

```tsx
import { IMyComponent, Something } from './types'
import { WrongStringError } from './errors'

export function createMyNewComponent(
  components: Pick<AppComponents, 'logs'>
): IMyComponent {
  const { logs } = components
  const logger = logs.getLogger('my-component')

  // 内部方法 - 不对外暴露
  function computeString(fstString: string, sndString: string): string {
    if (fstString.length === 0) {
      throw new WrongStringError()
    }
    
    return fstString + ' ' + sndString
  }

  // 公共方法 - 在返回对象中暴露
  function myFunction(): boolean {
    return true
  }

  // 公共方法 - 在返回对象中暴露
  function getSomething(): Something {
    logger.info('正在获取某些内容')
    
    return {
      aValue: true,
      anotherValue: computeString('aString', 'anotherString')
    }
  }

  // 返回公共 API
  return {
    myFunction,
    getSomething
  }
}
```

## 错误文件

错误文件包含组件可以抛出的自定义错误类。这些错误可在其他组件或控制器中使用，以便正确识别并处理特定错误情况。

### 示例： `errors.ts`

```tsx
export class WrongStringError extends Error {
  constructor(message?: string) {
    super(message || '字符串不正确')
    this.name = 'WrongStringError'
  }
}

export class ComponentNotInitializedError extends Error {
  constructor() {
    super('Component has not been initialized')
    this.name = 'ComponentNotInitializedError'
  }
}
```

### 错误处理最佳实践

* 为不同的错误情况创建特定的错误类
* 包含有意义的错误消息
* 将 `名称` 属性应与类名匹配，以便更轻松地调试
* 记录每个公共方法可能抛出的错误

## 索引文件

索引文件作为组件的公共入口点，仅导出应用程序其他部分应该能访问的内容。

### 示例： `index.ts`

```tsx
export { createMyNewComponent } from './component'
export type { IMyComponent, Something } from './types'
export { WrongStringError } from './errors'
```

## 最佳实践

1. **单一职责** - 每个组件都应只有一个明确的用途
2. **显式依赖** - 所有依赖都应通过 components 参数注入
3. **不可变性** - 尽可能优先使用不可变数据结构
4. **错误处理** - 为不同的错误情况使用自定义错误类
5. **日志记录** - 使用日志记录器进行调试和监控
6. **类型安全** - 充分利用 TypeScript 的类型系统
7. **文档** - 记录复杂的方法和业务逻辑

## 组件生命周期

某些组件可能需要执行初始化或清理操作。WKC 提供了生命周期方法：

* `[START_COMPONENT]` - 在组件启动时调用
* `[STOP_COMPONENT]` - 在组件停止时调用

请参阅 [适配器](/contributor/contributor-zh/gong-xian-zhe-zhi-nan/yi-zhi-zu-jian/adapters.md) 使用生命周期方法的组件示例部分。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.decentraland.org/contributor/contributor-zh/gong-xian-zhe-zhi-nan/yi-zhi-zu-jian/components.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
