---
sidebar_position: 3
---

# 物料接入

Tango 提供了低成本的物料接入方式，支持直接复用现有的组件体系。只需要在现有组件包基础上简单的提供配置说明问题，即可轻松接入到 Tango 低代码生态体系中。

import Link from '@docusaurus/Link';

## 预览视图和设计器视图

- 预览视图：是组件默认的渲染模式，通常我们只需要关注此视图行为。
- 设计器视图：为低代码平台定制的渲染视图，当我们需要自定义组件在 Tango 设计器中的部分渲染行为时，可以通过修改设计器视图的渲染逻辑实现。

### 设计器视图和 `withDnd`

通常情况下我们不需要太关注于设计器视图，只需通过 `withDnd` 简单的进行包装即可。例如：

```jsx
// 将 antd Button 包装一层提供设计器视图
export Button = withDnd({
  name: 'Button', // 必须，组件的名字，用来正确设置组件的 displayName
  isFunctionComponent: true, // 可选，如果包裹的组件为函数组件，可以在此设置
  overrideProps: {}, // 可选，覆盖掉包裹组件的默认属性值
})(AntButton);
```

默认情况下 withDnd 会在组件外层包裹一层 dnd 容器，以便于组件能够在设计器中被拖拽：

- draggable 属性表示该区域可以被拖拽
- data-dnd 用来追踪渲染的 dom 元素

```jsx
<div className="dnd-wrapper" draggable data-dnd="button:123">
  <button>hello</button>
</div>
```

### 自定义拖拽容器

由于默认情况下拖拽容器是一个 `div` 节点，为[块级元素](https://www.w3schools.com/cssref/pr_class_display.asp)。部分情况下，你可能期望它渲染为一个[行内容器](https://www.w3schools.com/cssref/pr_class_display.asp)，此时可以通过如下方式配置：

```jsx
export Button = withDnd({
  name: 'Button',
  display: 'inline-block', // 将 dnd 容器渲染为行内元素
  wrapperStyle: {}, // 传入 dnd 容器的自定义样式
})(AntButton);
```



### 禁用拖拽容器

某些情况下，你的组件可能会检查子节点的有效性，此时你可能不期望组件被包装额外的容器节点，此时你可以关闭拖拽容器，但你需要保证你的组件能够接收父级元素传入的属性信息并附加到组件的跟节点上，否则将无法正确的设置组件的 dnd 信息。

```jsx
export Button = withDnd({
  name: 'Button',
  hasWrapper: false, // 禁用拖拽容器
})(MyButton);

const MyButton = (props) => {
  const { children, ...rest } = props;
  // 此时，需要保证你的组件能够正确的将多余的属性透传到组件的根节点上
  return <button {...rest}>{children}</button>
}
```

## 组件包接入

组件包一般包含多个组件导出，例如 `@music163/antd` 就是典型的组件包，它面向中后台场景提供统一的物料层解决方案。组件包接入 Tango 体系，无需修改现有的代码实现，只需要在此基础上提供额外的配置文件即可。如下所示：

```
- src
  - button
    - designer.tsx # 设计器视图，可以不提供
    - index.ts # 默认视图出口
    - prototype.ts # 组件可配置描述协议
- index.ts
- prototypes.ts
- designer.ts
```

参考示例：https://g.hz.netease.com/NeteaseMusicUI/music-one/-/tree/master/packages/components/src/action

### 设计器视图的实现

对大部分组件而言，都不需要提供特定的设计器视图，只需要使用 tango 提供的 dnd hoc 进行简单的包裹导出即可。

```tsx
import { Button as Base, ButtonProps } from 'antd';
import { withDnd } from '@music/tango-apps-shared';

export const Button = withDnd<HTMLDivElement, ButtonProps<any>>({
  name: 'Button',
})(Base);
```

### 编写 prototypes 文件

可以参考 <Link to="/docs/protocol/material-protocol">物料协议</Link> 编写该文档

### 属性设置器选择

参考属性设置器文档进行选择。

### 可配置项的验证

TangoApps 提供了 SettingFormPlayground 组件用来测试组件的可配置能力，可以直接在组件文档中加入可配置测试示例，例如在 storybook 中进行测试。

```jsx
import React from 'react';
import { SettingFormPlayground } from '@music/tango-apps-setting-form';
import { Input, prototypes } from '@music163/antd';

export default {
  title: 'Prototype/Input',
};

export function Basic() {
  return (
    <SettingFormPlayground prototype={prototypes.Input}>
      <Input />
    </SettingFormPlayground>
  );
}
```

SettingFormPlayground 组件支持实时预览配置结果，预览效果如下：

<img src="https://p6.music.126.net/obj/wonDlsKUwrLClGjCm8Kx/13140796879/edbb/5dad/a330/013a98940e487956b605e1e533f54371.png" />

## 单个业务组件接入

单个组件接入可以参考组件包的接入方案。

:::info
考虑到单组件形态的特点，在云音乐业务场景中，TangoStudio 将会与红石物料中心对接，提供业务组件的自动化接入能力，目前该能力正在开发过程中。
:::
