zarm
Version:
基于 React 的移动端UI库
234 lines (217 loc) • 11.7 kB
Markdown
# Popup 弹出框
## 基本用法
```jsx
import { useState, useReducer, useRef } from 'react';
import { Popup, List, Button, Picker, Toast } from 'zarm';
const SINGLE_DATA = [
{ value: '1', label: '选项一' },
{ value: '2', label: '选项二' },
];
const initVisibleState = {
popBottom: false,
popTop: false,
popLeft: false,
popRight: false,
picker: false,
popSpec: false,
popCenterSpec: false,
};
const Demo = () => {
const popupRef = useRef();
const timer = useRef();
const [value, setValue] = useState('');
const [visible, setVisible] = useReducer((state, action) => {
const { type } = action;
return {
...state,
[type]: !state[type],
};
}, initVisibleState);
const toggle = (type) => setVisible({ type });
return (
<>
<List>
<List.Item
title="从上方弹出"
suffix={
<Button
size="xs"
onClick={() => {
toggle('popTop');
timer.current && clearTimeout(timer.current);
timer.current = setTimeout(() => {
toggle('popTop');
}, 3000);
}}
>
开启
</Button>
}
/>
<List.Item
title="从下方弹出"
suffix={
<Button size="xs" onClick={() => toggle('popBottom')}>
开启
</Button>
}
/>
<List.Item
title="从左侧弹出"
suffix={
<Button size="xs" onClick={() => toggle('popLeft')}>
开启
</Button>
}
/>
<List.Item
title="从右侧弹出"
suffix={
<Button size="xs" onClick={() => toggle('popRight')}>
开启
</Button>
}
/>
<List.Item
title="从中间弹出"
suffix={
<Button size="xs" onClick={() => toggle('popCenter')}>
开启
</Button>
}
/>
<List.Item
title="自定义挂载节点"
suffix={
<Button size="xs" onClick={() => toggle('popSpec')}>
开启
</Button>
}
/>
</List>
<Popup
visible={visible.popTop}
direction="top"
mask={false}
afterClose={() => console.log('关闭')}
>
<div className="popup-box-top">更新成功</div>
</Popup>
<Popup
visible={visible.popBottom}
direction="bottom"
onMaskClick={() => toggle('popBottom')}
destroy={false}
mountContainer={() => document.body}
>
<div className="popup-box">
<Button size="xs" onClick={() => toggle('picker')}>
打开Picker
</Button>
<Picker
visible={visible.picker}
value={value}
dataSource={SINGLE_DATA}
onConfirm={(selected) => {
console.log('Picker onConfirm: ', selected);
Toast.show(JSON.stringify(selected));
setValue(selected.map((item) => item.value));
toggle('picker');
}}
onCancel={() => toggle('picker')}
mountContainer={() => document.body}
/>
</div>
</Popup>
<Popup
visible={visible.popLeft}
onMaskClick={() => toggle('popLeft')}
direction="left"
afterClose={() => console.log('关闭')}
>
<div className="popup-box-left">
<Button size="xs" onClick={() => toggle('popLeft')}>
关闭弹层
</Button>
</div>
</Popup>
<Popup visible={visible.popRight} onMaskClick={() => toggle('popRight')} direction="right">
<div className="popup-box-right">
<Button size="xs" onClick={() => toggle('popRight')}>
关闭弹层
</Button>
</div>
</Popup>
<Popup visible={visible.popCenter} direction="center" width="70%">
<div className="popup-box">
<Button size="xs" onClick={() => toggle('popCenter')}>
关闭弹层
</Button>
</div>
</Popup>
<Popup
visible={visible.popSpec}
onMaskClick={() => {
if (visible.popCenterSpec) {
toggle('popCenterSpec');
}
toggle('popSpec');
}}
onEsc={() => {
toggle('popSpec');
}}
ref={popupRef}
destroy={true}
>
<div className="popup-box-bottom">
<Button size="xs" onClick={() => toggle('popCenterSpec')}>
打开弹层
</Button>
<p>打开的modal挂载此popup上</p>
<Popup
visible={visible.popCenterSpec}
direction="center"
width="70%"
onEsc={() => {
toggle('popCenterSpec');
}}
mountContainer={() => {
return popupRef.current;
}}
>
<div className="popup-box">
<Button size="xs" onClick={() => toggle('popCenterSpec')}>
关闭弹层
</Button>
</div>
</Popup>
</div>
</Popup>
</>
);
};
ReactDOM.render(<Demo />, mountNode);
```
## API
| 属性 | 类型 | 默认值 | 说明 |
| :---------------- | :------------------- | :------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| visible | boolean | false | 是否显示 |
| direction | string | 'bottom' | 弹出方向,可选值 `top`, `bottom`, `left`, `right`, `center` |
| animationType | string | 'fade' | 当弹出方向为中间位置(direction="center")时的动画效果,可选值 `fade`, `door`, `flip`, `rotate`, `zoom`, `move-up`, `move-down`, `move-left`, `move-right`,`slide-up`, `slide-down`, `slide-left`, `slide-right` |
| animationDuration | number | 200 | 动画执行时间(单位:毫秒) |
| width | string | number | - | 弹层宽度 |
| mask | boolean | true | 是否展示遮罩层 |
| maskClassName | string | - | 遮罩层的样式名 |
| maskStyle | React.CSSProperties | - | 遮罩层的样式 |
| maskColor | string | 'black' | 遮罩层的颜色,可选值 `black`, `white`, `transparent` |
| maskOpacity | string \| number | 'normal' | 遮罩层的透明度,可选值 `normal`, `light`, `dark`,或填写具体数值(0 ~ 1) |
| forceRender | boolean | false | 强制渲染内容 |
| destroy | boolean | true | 弹层关闭后是否移除节点 |
| onOpen | () => void | - | 弹层展示的回调 |
| onClose | () => void | - | 弹层关闭的回调 |
| afterOpen | () => void | - | 弹层展示后的回调 |
| afterClose | () => void | - | 弹层关闭后的回调 |
| onMaskClick | () => void | - | 点击遮罩层时触发的回调函数 |
| onEsc | () => void | - | 点击 Esc 键时触发的回调函数 |
| mountContainer | MountContainer | () => document.body | 指定 Popup 挂载的 HTML 节点 |
| lockScroll | boolean | true | 锁定背景滚动 |