# 介绍
此项目是把原来的 **T**alent **U**I **B**uilder中的核心的功能分离了出来，方便不同的项目进行接入


# 使用说明

### 安装到项目中
```shell
npm install @beisen/tub --save
```

### Class
```js
export default Workspace;
export {UIBuilderState, Workspace, Viewer};
```

#### Workspace *[ReactComponent]*
**编辑器** 

#### Viewer *[ReactComponent]*
**渲染器** 

#### TubState *[static class]*
**数据**



### 示例代码 
**编辑器**
```js
//引入Tub
import Workspace, {Tub} from '@beisen/tub';
//引入样式
import '@beisen/tub/style.css';
```


```js
//组件代码
class Home extends Component {

  constructor(props, contents){
    super();
    this.state = {tubState: TubState.create()};
  }

  handleChange(tubState){
     this.setState({tubState})
  }

  render() {
    return (
        <Workspace 
          components={components}
          propsComponents={propsComponents}
          templates={templates}
          previewUrl="#/view"
          onChange={::this.handleChange}
          onSave={::this.handleSave}
          />
          
    );
  }
}
```

**渲染器**

```js
import {Viewer, UIBuilderState} from '@beisen/tub';
import '@beisen/tub/style.css';

export default class View extends Component{
    constructor(props){
        super(props)
        let data = JSON.parse(window.localStorage.uibuilder)
        this.state = {
            tubState: TubState.create(data)
        }
    }

    renderComponent(Comp,data, mergeProps){
        return <Comp data={data} {...mergeProps}/>
    }

    componentWillReceiveProps(nextProps){
        this.setState({
            tubState: tubState.setContent(nextProps.data)
        });
    }
    
    render(){
        return <Viewer  
                tubState={this.state.tubState}
                components={Elements} 
                templates={PageTemplate}
                renderComponent={::this.renderComponent}
                onChange={(tubState) => {this.setState({tubState})}}
            />
    }
}
```


### 参数说明

##### **components** *[object]*  __Workspace & Viewer__
供拖拽的组件列表

**项目代码示例**

```js
import Text from './Text';
import LinkList from './LinkList';
import Form from './Form';
import Header from './Header';
import DataTable from './DataTable';
import ImgSlider from './ImgSlider';
import VideoPlayer from './Video';
import ButtonGroup from './ButtonGroup';
import MoChart from './MoChart';
import Charts from './Charts'
import MoFilters from './MoFilters';

export default {
    ButtonGroup,
    DataTable,  
    LinkList, 
    Form, 
    Header, 
    MoChart,  
    ImgSlider, 
    Text, 
    VideoPlayer,
    Charts, 
    MoFilters,
};
```

##### **propsComponents** *[object]* __Workspace__
给组件提供属性编辑的组件列表

##### **templates** *[object]* __Workspace & Viewer__
页面可用的模板列表

##### **tubState** *[instance of TubState]* __Workspace & Viewer__
通过 **UIBuilderState** 创建state的key, UI Builder编辑的结果可以用这个key取出来

##### **previewUrl** *[string]* __Workspace__
预览结果的地址，因为模拟设备需要使用iframe来模拟尺寸，所以需要在本地部署一个viewer来展示编辑的结果

##### **onSave** *[function]* __Workspace__
点击保存按钮的时候执行的回调

#### **onChange** *[function]* __Workspace & Viewer__ 

#### **renderComponent** *function* __Workspace & Viewer__
定义

```js
 function renderComponent(Comp){
	/* 自定义的组件渲染方法
	 * @Comp, 用来渲染的组件
	 * 请注意 data属性是用来接收editableData的属性，请不要覆盖此属性
	*/
	//示例
	return <Comp />
}
```

### 关于模板
在Tub中，模板是Workspace和Viewer都支持的一属性，是用来渲染创建的页面的公共内容的。开发者可以以开发组件的方式开发出一个模板，并通过this.props.children指定自定义布局的区域。

除了模板有固定的可配置的属性外，还支持getEditProps方法，为模板定制可配置的属性。方法同组件配置可编辑属性。
详情参见项目中的examples

##### 示例代码



### 关于属性编辑

在使用UI Builder编辑器的时候需要传入components和propComponents

components是展示的组件，
propComponents是对组件进行编辑的组件

在对开发一个components组件时，需要定义一个静态属性， 下面是一个最简单的components, 只有一个可编辑属性

**展示组件的示例代码**
```js
class Text extends Component {
   
    static getEditProps(){
        return [
            {
                pType: 'PropsText', //propComponent 类型
                name: '编辑内容', //在属性编辑面板的显示名字
                key: 'value', //编辑结果存储的key,
                defaultValue: 'text' //此字段的默认值
            }
        ]
    }
    
    render() {
        let {mode, data/*数据*/ } = this.props;
        if(mode===1){
            return <div>Text Preview</div>
        }else{
            return <div>{data.value/*从数据中取编辑结果的字段*/ || 'Text'}</div>
        }
    }
}

export default Text;
```

**编辑属性组件的代码**

```js
import React, {Component, PropTypes} from 'react';
import './Text.scss'
import {Input} from 'components/common/form'

class PropsText extends Component {

    handleSave(val) {
    		//this.props.update方法所有属性编辑组件都可以使用，表示应用编辑结果
        let {update} = this.props; 
        update(val) 果
    }

    render() {
    		/*
    			因为一个属性编辑组件只对应展示组件中的一个属性字段，所以数据统一放在this.props.data中
    		*/
    		let {data} = this.props;
        return <Input value={data} placeholder='空白内容'
            onChange={this.handleSave.bind(this) } />
    }
}

export default PropsText;
```

## 组件通信机制

#### 流程




