# 创建和使用自定义组件

你可以将小程序页面内的功能模块抽象成自定义组件，以便在不同的页面中重复使用，也可以将复杂的页面拆分成多个低耦合的模块，以便维护代码，本文将介绍如何创建和使用小程序的自定义组件。

自定义组件在使用上与基础组件相似，关于小程序基础组件的信息，可参见[基础组件](https://open.feishu.cn/document/uYjL24iN/ugTNugTNugTN)。

## 前提条件

飞书客户端从 V1.18 版本开始支持小程序简洁的组件化编程能力。因此，当你在使用小程序自定义组件相关特性时，需要确保飞书客户端的版本为 V1.18 及以上。

## 创建自定义组件

自定义组件类似于页面，一个自定义组件由 `json`、 `ttml`、`ttss`、`js` 4 个文件组成。创建一个自定义组件的操作流程如下所示。

1. 在 `json` 文件中，声明自定义组件。

将 `component` 字段取值为 `true`，表示把一组 `json`、 `ttml`、`ttss`、`js` 文件定义为自定义组件。

```js
    {
      "component": true
    }
    ```

2. 在 `ttml` 文件中编写组件模版，在 `ttss` 文件中加入组件样式。

组件模板和样式的写法，与页面的写法类似，详情参见[组件模版和样式](https://open.feishu.cn/document/uYjL24iN/ukTOukTOukTO)。

示例代码 (自定义组件的内部 TTML 结构)：

```html
    <view class="my-custom-component">
      <text class="header">{{ headerText }}</text>
      <view class="content">
        <slot></slot>
      </view>
    </view>
    ```

相应的样式代码如下，该样式代码只应用于当前自定义组件。

```css
    .header {
      color: green;
    }
    ```

3. 在自定义组件的 `js` 文件中，使用 `Component()` 注册组件，并提供组件的属性定义、内部数据和自定义方法。

组件的属性值和内部数据将用于组件 `ttml` 的渲染，其中，属性值可由组件外部传入。更多说明，参见 [Component 构造器](https://open.feishu.cn/document/uYjL24iN/uADMx4CMwEjLwATM)。

```js
    Component({
      properties: {
        // 这里定义了 headerText 属性，属性值可以在组件使用时指定
        headerText: {
          type: String,
          value: '默认标题文案',
        }
      },
      data: {
        // 组件内部数据
        defaultStates: {}
      },
      methods: {
        // 自定义方法
        customMethod: function(){}
      }
    })
    ```

## 使用自定义组件

创建好自定义组件后，即可使用自定义组件。使用流程如下所示。

1. 使用自定义组件前，先在页面的 `json` 文件中进行引用声明，提供每个自定义组件的标签名和对应的自定义组件文件路径。

```js
    {
      "usingComponents": {
        "my-component": "path/to/a/custom/component"
      }
    }
    ```

2. 在页面的 `ttml` 中选择使用自定义组件（使用方式类似于基础组件）。

节点名即自定义组件的标签名，节点属性即传递给组件的属性值。

```html
    <view class="component-wrapper">
      <my-component header-text="My Title"></my-component>
    </view>
    ```

自定义组件的 `ttml` 节点结构在与数据结合之后，将被插入到引用位置内。

- 由于 `ttml` 节点标签名只能使用小写字母、中划线和下划线的组合，因此，相应的自定义组件的标签名也只能只能使用小写字母、中划线和下划线的组合。

- 自定义组件支持引用其他自定义组件，引用方式与页面引用自定义组件的方式类似，即使用 `usingComponents` 字段进行引用。

- 自定义组件不能与小程序原生组件重名。

