# SidePane

## 何时使用

直接将内容渲染至具体的dom节点时使用。

业务需求：通常用于规则驱动页面时使用，组件的销毁需要主动销毁，因此即使触发组件生命周期 `componentWillUnmount` 也不会从 `dom` 中移除。

> 注意，该案例页面，如果路由切换时，组件并未销毁，此时演示组件功能，请刷新后重试。

## 案例演示

### 基本使用

---demo
```js
import { StdForm, SidePane, Slider } from 'amos-framework';

const CombineSlider = Slider.CombineSlider;

class Demo extends Component {

  constructor(props) {
    super(props);
    this.state = {
      left: 10,
      top: 64
    };
  }

  onChange = (type, value) => {
    this.setState({
      [type]: value
    });
  }

  render() {
    const { left, top } = this.state;
    return (
      <div style={{ width: '25em', display: 'inline-block' }}>
        <StdForm label="left">
          <CombineSlider
            min={0}
            max={1000}
            onChange={v => this.onChange('left', v)}
            value={left}
            style={{ width: '18em' }}
          />
        </StdForm>
        <StdForm label="top">
          <CombineSlider
            min={0}
            max={700}
            onChange={v => this.onChange('top', v)}
            value={top}
            style={{ width: '18em' }}
          />
        </StdForm>
        <SidePane left={left} top={top}>
          <ul style={{ background: '#ccc', padding: '2em' }}>
            <li>侧边按钮1</li>
            <li>侧边按钮2</li>
            <li>侧边按钮3</li>
            <li>侧边按钮4</li>
            <li>侧边按钮5</li>
          </ul>
        </SidePane>
      </div>
    );
  }
}

ReactDOM.render(<Demo />, _react_runner_);
```
---demoend

### 启用动画

在显示与隐藏时，启用动画效果

---demo
```js
import { StdForm, SidePane, Switch } from 'amos-framework';

class Demo extends Component {

  constructor(props) {
    super(props);
    this.state = {
      visible: true,
      animateDelay: 0
    };
  }

  onChange = (onOff) => {
    this.setState({
      visible: onOff
    });
  }

  onDelayChange = (value) => {
    this.setState({
      animateDelay: value
    });
  }

  render() {
    const { visible, animateDelay } = this.state;
    const animateProps = {
      transitionAppear: true
    };
    return (
      <div style={{ width: '25em', display: 'inline-block' }}>
        <StdForm label="延时">
          <InputNumber value={animateDelay} type="outer" min={0} max={10} onChange={this.onDelayChange} />
        </StdForm>
        <StdForm label="显示/隐藏">
          <Switch onOff={visible} onChange={this.onChange} />
        </StdForm>
        <SidePane
          left={330}
          top={728}
          animateName="zoom-up"
          visible={visible}
          animateProps={animateProps}
          animateDelay={animateDelay}
        >
          <ul style={{ background: '#ccc', padding: '2em' }}>
            <li>列表1</li>
            <li>列表2</li>
            <li>列表3</li>
            <li>列表4</li>
            <li>列表5</li>
          </ul>
        </SidePane>
      </div>
    );
  }
}

ReactDOM.render(<Demo />, _react_runner_);
```
---demoend

### 自定义渲染 Container

通过设置 `getContainer` 使面板渲染在指定的节点。如果采用 `ref` 方式赋值给 `getContainer`，依据 `react` 加载原理，此时需要设置给 `SidePane` 之前的兄弟节点。注意：不能直接赋给其父节点。

---demo
```js
import { SidePane } from 'amos-framework';

class Demo extends Component {
  saveRef = node => this.containerRef = node;

  getContainer = () => {
    return this.containerRef;
  };

  render() {
    const animateProps = {
      transitionAppear: true
    };
    return (
      <div
        style={{
          width: '25em',
          height: '15em',
          display: 'inline-block'
        }}
      >
        <div style={{ position: 'relative' }} ref={this.saveRef}/>
        <SidePane
          left={20}
          top={20}
          animateName="zoom-up"
          visible
          animateProps={animateProps}
          animateDelay={3}
          getContainer={this.getContainer}
        >
          <ul style={{ background: '#ccc', padding: '2em' }}>
            <li>3秒过后渲染在指定节点区域</li>
            <li>列表1</li>
            <li>列表2</li>
            <li>列表3</li>
            <li>列表4</li>
            <li>列表5</li>
          </ul>
        </SidePane>
      </div>
    );
  }
}

ReactDOM.render(<Demo />, _react_runner_);
```
---demoend

### 自定义 Container 滞后显示（PortalSidePane）

采用 `PortalSidePane` 可直接将 `getContainer` 返回值采用父节点的 ref 进行设置。初始为 true 无法直接显示。如果初始加载就要显示，需要按照上一个案例的方式进行

---demo
```js
import { PortalSidePane, Switch } from 'amos-framework';

class Demo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      visible: true
    };
  }

  onChange = (onOff) => {
    this.setState({
      visible: onOff
    });
  }

  saveRef = node => this.containerRef = node;

  getContainer = () => {
    return this.containerRef;
  };

  render() {
    const { visible } = this.state;
    const animateProps = {
      transitionAppear: true
    };
    return (
      <div
        style={{
          width: '25em',
          height: '17em',
          display: 'inline-block',
          position: 'relative'
        }}
        ref={this.saveRef}
      >

        <StdForm label="显示/隐藏">
          <Switch onOff={visible} onChange={this.onChange} />
        </StdForm>
        <PortalSidePane
          left={20}
          top={20}
          animateName="zoom-up"
          visible={visible}
          animateProps={animateProps}
          animateDelay={1}
          getContainer={this.getContainer}
        >
          <ul style={{ background: '#ccc', padding: '2em' }}>
            <li>切换显隐，将渲染在指定节点区域</li>
            <li>列表1</li>
            <li>列表2</li>
            <li>列表3</li>
            <li>列表4</li>
            <li>列表5</li>
          </ul>
        </PortalSidePane>
      </div>
    );
  }
}

ReactDOM.render(<Demo />, _react_runner_);
```
---demoend

## props

| params | type | default | description |
|--------- |-------- |--------- |-------- |
| prefixCls | string | `amos-sidepane` | 组件默认clssname prefix |
| className | string | - | 组件自定义clssname |
| style | object | {} | 组件自定义样式 |
| left | number or false | 10 | 至屏幕左侧距离，设置为 `false 或 null`，则可以取消 left 设置 |
| top | number or false | 64 | 至屏幕顶部距离，设置为 `false 或 null`，则可以取消 top 设置 |
| right | number or false | - | 至屏幕右侧距离，设置为 `false 或 null`，则可以取消 right 设置 |
| bottom | number or false | - | 至屏幕底部距离，设置为 `false 或 null`，则可以取消 bottom 设置 |
| children | ReactNode | - | 需要渲染的具体节点 |
| beforeRemove | func | - | 卸载dom之前执行 |
| getContainer | func | - | 获取自定义渲染目标dom，默认为：在 body 下创建一个div。 |
| animateName | string | - | 动画名称，具体支持的值，详见 [Animate](/#/framework/animate) |
| animateProps | object | - | 动画参数，详见组件 [Animate](/#/framework/animate) |
| visible | boolean | - | 当启用动画渲染时，该 props 用于控制动元素显隐时动画参数 |
| animateDelay | number | - | 开启动画渲染时，设置动画延迟执行时间，单位为 `s` |

> 独立设置 `left、top、right、bottom` 将会覆盖 `style` 中的相应值，应用到界面中，单位为 `px`。

注意： 当不设置 `animate` 时，visible 属性不控制 SidePane 的显隐

> 当采用 `ref` 方式，给 `getContainer` 传递数据时，初始就显示的情况下，不能采用父节点的 ref 数据，这是由 `react` 生命周期加载顺序决定的，父组件执行 `componentDidMount` 的总是在所有的 children 组件执行完 `componentDidMount`
之后才执行。而 `ref` 的执行时机，也是在 `componentDidMount` 执行之后。使用方式：可以按照示例中设置，或者采用 `dom` 获取的方式进行。
