# 组件文档

基于 Taro 框架的惟客云 C 端通用组件库。

组件库目前还是测试阶段，欢迎使用和给我们[提 Issue 和需求](http://gitlab.wakedata-inc.com/wakeapp/tools/-/issues)。

> 注意, 文档的预览效果会差于小程序真机。

<br>
<br>

## 安装

<br>

```shell
$ pnpm add @wakeapp/components
$ pnpm add @wakeapp/taro-components-react @wakeapp/taro-plugin @wakeapp/babel-plugin-transform-wkicon babel-plugin-import -D
```

其他包管理工具同理:

```shell
$ npm i @wakeapp/components --save
$ npm i @wakeapp/taro-components-react @wakeapp/taro-plugin @wakeapp/babel-plugin-transform-wkicon babel-plugin-import --save-dev
```

<br>
<br>

## 初始化

<br>

Taro 配置, 修改 config/index.js

```js
const config = {
  // ...
  plugins: [
    // 添加插件
    '@wakeapp/taro-plugin',
  ],
  // ...
};
```

<br>
<br>

Babel 配置，支持组件、icon 按需加载，babel 配置示例:

```js
const componentImportOptions = require('@wakeapp/components/babel-import-config');

module.exports = {
  plugins: [
    // 组件按需加载
    ['babel-plugin-import', componentImportOptions],
    // 转换 icon
    '@wakeapp/babel-plugin-transform-wkicon',
  ],
  // ... 其他配置
};
```

<br>
<br>

初始化组件库, 在 `src/app.tsx` 加入下述代码：

```tsx | pure
import { initialWakeappComponents } from '@wakeapp/components';

initialWakeappComponents();

export class App extends Component {
  // Taro 应用
}
```

<br />
<br />

## 使用

我们推荐不管是 Taro 的原生组件还是惟客组件，都通过 @wakeapp/components 导入：

<br>

```tsx | pure
// View 是 原生组件
// WK* 前缀的为 惟客组件
import { View, WKDialog } from '@wakeapp/components';

// 统一使用 @wakeapp/api 而不是 @tarojs/taro
import api from '@wakeapp/api';
```

<br>
<br>

### 多语言支持

@wakeapp/components 默认仅支持中文，如果需要其他语言, 可以自行注册:

```tsx | pure
import { initializeI18n } from '@wakeapp/i18n';

// 在 App 实例化之前调用
// 组件库在 0.2.0 之后支持多语言，确保先初始 i18n
initializeI18n();

registerBundles({
  'zh-Hant': require('@wakeapp/components/locale/zh-Hant.json?extra'),
  en: require('@wakeapp/components/locale/en.json?extra'),
});
```

你也可以参照现有语言包的结构扩展其他语言。

<br>
<br>

## 主题配置

@wakeapp/components 支持配置主题变量来控制整体的呈现，满足业务的定制化需求。

默认情况下，@wakeapp/components 使用的是 [设计](../design) 中定义的默认变量。 你也可以覆盖这些变量配置:

在 Taro app.tsx 中定义：

```tsx | pure
import { WKThemeProvider, ITheme } from '@wakeapp/components';

const YourTheme: Partial<ITheme> = {
  // 定义你自己的主题
};

export default class App {
  render() {
    return <WKThemeProvider value={YourTheme}>{this.props.children}</WKThemeProvider>;
  }
}
```

<br>
<br>

## 使用主题变量

使用主题变量有很多种方式。

<br>

### 方式 1： 使用 styled 创建组件

```tsx | pure
import { styled, View } from '@wakeapp/components';

// 创建组件
// 定义在 styled 中的样式属性、rpx 等会被自动转换
const MyView = styled({
  // 使用 CSS Variable 形式访问
  color: 'var(--primary-color)',

  // 也支持回调形式
  backgroundColor: t => t.secondaryColor,
  width: '100%',
  height: '100rpx',
});

// 使用
export const MyComponent = () => {
  return (
    <MyView>
      <View>hello</View>
    </MyView>
  );
};
```

<br>
<br>

### 方式 2： 使用 useWKTheme

```tsx | pure
import api from '@wakeapp/api';
import { useWKTheme, View } from '@wakeapp/components';

export const MyComponent = () => {
  const t = useWKTheme();

  return (
    <View
      style={{
        color: t.primaryColor,
        backgroundColor: t.secondaryColor,
        width: '100%',
        height: api.pxTransform(100),
      }}
    >
      <View>hello</View>
    </View>
  );
};
```

<br>
<br>

### 方式 3： CSS 样式表

```scss | pure
.my-view {
  // 使用 CSS 变量访问
  color: var(--primary-color);
  background-color: var(--secondary-color);
  width: 100%;
  height: 100px; // Taro 默认会将 px 转换为 rpx
}
```

<br>

```tsx | pure
import { View } from '@wakeapp/components';
import './index.scss';

export const MyComponent = () => {
  const t = useWKTheme();

  return (
    <View className="wk-view">
      <View>hello</View>
    </View>
  );
};
```

> ⚠ ️ CSS 样式表形式使用比较简单，但未来可能不兼容 App 端。

<br>
<br>

## 页面样式

初始化 @wakeapp/components 后，所有 Taro 页面都会包裹一个 root 节点。 @wakeapp/components 的对话框、主题变量注入、Toast 等 API 的实现都依赖于它。

<br>

<img src="./root.png" width="500" />

<br>

**为什么要包裹 root 节点？**

小程序每个页面都是独立的。不存在类似 HTML 的 body 节点。
因此，为了实现自动的主题变量注入，以及 `WKDialog.confirm()` 这样的 API。我们全局拦截了 Taro 的页面渲染，给每个页面都包裹了一个 root 节点。将主题变量注入到这个 root 节点中，另外也支持动态将 WKDialog.confirm() 渲染内容插入到 root 节点下。

另一个原因是，微信小程序的 page 节点不是跨平台的。而且我们无法给 page 节点加上 CSS 类来隔绝样式冲突。现在 C 端就存在一些这样的样式:

```css
page {
  height: 100%;
  background: rgba(240, 241, 245, 1);
  font-family: PingFangSC-Regular;
}
```

这种样式只适用于微信小程序，而且**所有页面**都会生效这个规则，导致页面之间互相污染(比如 A 页面是黑色，另一个页面是红色，那最终是什么颜色呢？无法预测)。

<br>
<br>

使用 @wakeapp/components 后，我们可以这样设置页面的样式:

```tsx | pure
import { WKPageStyle } from '@wakeapp/components';

export const MyPage: FC = () => {
  return (
    <View>
      <WKPageStyle className="my-page" />
    </View>
  );
};
```

或者

```tsx | pure
import { WKPageStyle } from '@wakeapp/components';

export const MyPage: FC = () => {
  return (
    <View>
      <WKPageStyle style={{ backgroundColor: 'white' }} />
    </View>
  );
};
```

添加到 WKPageStyle 的 className 和 style 将设置到 root 节点中。
