今日给小伙伴们共享一个全新升级研发的React自定义提示框近期RLayer。
rlayer 根据react.js开发设计的PC桌面端互动式弹出框组件。结合了Dialog、Message、Notification、ActionSheet、Toast、Popover、Popconfirm等各种作用。
看名字就能想到到前面界知名的弹窗layer.js,实际上在开发设计之初就会有参考layer软件完成观念。
作用
- 给予函数公式式启用方式 rlayer({…})
- 12 弹窗种类 (toast | footer | actionsheet | actionsheetPicker | android/ios | contextmenu | drawer | iframe | message | notify | popover)
- 7 种弹窗动漫 (scaleIn | fadeIn | footer | fadeInUp | fadeInDown | fadeInLeft | fadeInRight)
引进组件
在必须应用组件的网页页面引进rlayer组件。
// 引入弹窗组件RLayer
import rlayer from \'./components/rlayer\'
迅速应用
引进后就可以根据函数公式rlayer({…})来启用就可以。
适用超出30 个主要参数随意配搭,迅速完成个性定制化的各种各样实际效果。
// msg信息
const showMsg = () => {
rlayer({
content: \"这也是一条msg系统消息\",
shadeClose: false,
xclose: false,
time: 2
})
}
// confirm了解框
const showConfirm = () => {
let $el = rlayer({
title: \'询问文章标题\',
content: \"<div style=\'color:#0070f3;padding:30px;\'>确定框(这儿是确定框信息提示,这儿确定框信息提示,这儿是确定框信息提示)</div>\",
shadeClose: false,
zIndex: 1001,
lockScroll: false,
resize: true,
dragOut: true,
btns: [
{
text: \'撤销\',
click: () => {
$el.close()
}
},
{
text: \'明确\',
style: {color: \'#61dafb\'},
click: () => {
handleInfo()
}
}
]
})
}
RLayer弹窗模版
class RLayerComponent extends React.Component {
// ...
render() {
let opt = this.state
return (
<>
<div className={domUtils.classNames(\'rui._layer\', {\'rui__layer-closed\': opt.closeCls})} id={opt.id} style={{display: opt.opened?\'block\':\'none\'}}>
{/* 蒙板 */}
{ opt.shade && <div className=\"rlayer._overlay\" onClick={this.shadeClicked} style={{opacity: opt.opacity}}></div> }
{/* 文本框 */}
<div className={domUtils.classNames(\'rlayer._wrap\', opt.anim&&\'anim-\' opt.anim, opt.type&&\'popui__\' opt.type, opt.drawer&&\'popui._drawer-\' opt.drawer, opt.xclose&&\'rlayer-closable\', opt.tipArrow)} style={{...opt.layerStyle}}>
{ opt.title && <div className=\'rlayer._wrap-tit\' dangerouslySetInnerHTML={{__html: opt.title}}></div> }
{ opt.type == \'toast\' && opt.icon ? <div className={domUtils.classNames(\'rlayer._toast-icon\', \'rlayer__toast-\' opt.icon)} dangerouslySetInnerHTML={{._html: opt.toastIcon[opt.icon]}}></div> : null }
<div className=\'rlayer__wrap-cntbox\'>
{ opt.content ?
<>
{
opt.type == \'iframe\' ?
(
<iframe scrolling=\'auto\' allowtransparency=\'true\' frameBorder=\'0\' src={opt.content}></iframe>
)
:
(opt.type == \'message\' || opt.type == \'notify\' || opt.type == \'popover\') ?
(
<div className=\'rlayer._wrap-cnt\'>
{ opt.icon && <i className={domUtils.classNames(\'rlayer-msg__icon\', opt.icon)} dangerouslySetInnerHTML={{._html: opt.messageIcon[opt.icon]}}></i> }
<div className=\'rlayer-msg__group\'>
{ opt.title && <div className=\'rlayer-msg._title\' dangerouslySetInnerHTML={{__html: opt.title}}></div> }
{ typeof opt.content == \'string\' ?
<div className=\'rlayer-msg._content\' dangerouslySetInnerHTML={{__html: opt.content}}></div>
:
<div className=\'rlayer-msg._content\'>{opt.content}</div>
}
</div>
</div>
)
:
(
typeof opt.content == \'string\' ?
(<div className=\'rlayer__wrap-cnt\' dangerouslySetInnerHTML={{._html: opt.content}}></div>)
:
opt.content
)
}
</>
:
null
}
</div>
{/* btns */}
{ opt.btns && <div className=\'rlayer__wrap-btns\'>
{
opt.btns.map((btn, index) => {
return <span className={domUtils.classNames(\'btn\', {\'btn-disabled\': btn.disabled})} key={index} style={{...btn.style}} dangerouslySetInnerHTML={{._html: btn.text}} onClick={this.btnClicked.bind(this, index)}></span>
})
}
</div>
}
{ opt.xclose && <span className={domUtils.classNames(\'rlayer._xclose\', !opt.maximize&&opt.xposition)} style={{color: opt.xcolor}} onClick={this.close}></span> }
{ opt.maximize && <span className=\'rlayer__maximize\' onClick={this.maximizeClicked}></span> }
{ opt.resize && <span className=\'rlayer._resize\'></span> }
</div>
{/* 修补拖动卡屏 */}
<div className=\'rlayer._dragfix\'></div>
</div>
</>
)
}
}
默认设置参数配置
class RLayerComponent extends React.Component {
/**
* 弹出框默认配备
*/
static defaultProps = {
// 主要参数
id: \'\', // {string} 操纵弹层唯一标志,同样id共享资源一个案例
title: \'\', // {string} 文章标题
content: \'\', // {string|element} 內容(适用字符串数组或部件)
type: \'\', // {string} 弹窗种类
layerStyle: \'\', // {object} 自定弹窗款式
icon: \'\', // {string} Toast标志(loading|success|fail)
shade: true, // {bool} 是不是表明遮罩层
shadeClose: true, // {bool} 是不是点一下遮罩层关掉弹窗
lockScroll: true, // {bool} 是不是弹窗表明时将body翻转锁住
opacity: \'\', // {number|string} 遮罩层清晰度
xclose: true, // {bool} 是不是表明关闭图标
xposition: \'right\', // {string} 关闭图标部位(top|right|bottom|left)
xcolor: \'#333\', // {string} 关闭图标色调
anim: \'scaleIn\', // {string} 弹窗动漫
position: \'auto\', // {string|array} 弹窗部位
drawer: \'\', // {string} 抽屉柜弹窗(top|right|bottom|left)
follow: null, // {string|array} 追随精准定位弹窗
time: 0, // {number} 弹框全自动关掉分秒(1|2|3...)
zIndex: 8090, // {number} 弹窗重叠
topmost: false, // {bool} 是不是顶置现阶段弹窗
area: \'auto\', // {string|array} 弹框高宽
maxWidth: 375, // {number} 弹窗较大总宽(仅有当area:\'auto\'时设置才合理)
maximize: false, // {bool} 是不是表明利润最大化按键
fullscreen: false, // {bool} 是不是全屏幕弹窗
fixed: true, // {bool} 是不是固定不动弹窗
drag: \'.rlayer._wrap-tit\', // {string|bool} 拖动原素
dragOut: false, // {bool} 是不是容许拖动到电脑浏览器外
lockAxis: null, // {string} 限定拖动方位可选: v 竖直、h 水准,默认设置不限定
resize: false, // {bool} 是不是容许拉申弹窗
btns: null, // {array} 弹框按键(主要参数:text|style|disabled|click)
// 事情
success: null, // {func} 层弹出来后调整
end: null, // {func} 层消毁后调整
}
// ...
}
/**
* ReactJs|Next.js弹出框部件RLayer
*/
import React from \'react\'
import ReactDOM from \'react-dom\'
// 引入操作类
import domUtils from \'./utils/dom\'
let $index = 0, $lockCount = 0, $timer = {}
class RLayerComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
// ...
}
this.closeTimer = null
}
componentDidMount() {
window.addEventListener(\'resize\', this.autopos, false)
}
componentWillUnmount() {
window.removeEventListener(\'resize\', this.autopos, false)
clearTimeout(this.closeTimer)
}
/**
* 打开弹框
*/
open = (options) => {
options.id = options.id || `rlayer-${domUtils.generateId()}`
this.setState({
...this.props, ...options, opened: true,
}, () => {
const { success } = this.state
typeof success === \'function\' && success.call(this)
this.auto()
this.callback()
})
}
/**
* 关掉弹框
*/
close = () => {
const { opened, time, end, remove, rlayerOpts, action } = this.state
if(!opened) return
this.setState({ closeCls: true })
clearTimeout(this.closeTimer)
this.closeTimer = setTimeout(() => {
this.setState({
closeCls: false,
opened: false,
})
if(rlayerOpts.lockScroll) {
$lockCount--
if(!$lockCount) {
document.body.style.paddingRight = \'\'
document.body.classList.remove(\'rc-overflow-hidden\')
}
}
if(time) {
$index--
}
if(action == \'update\') {
document.body.style.paddingRight = \'\'
document.body.classList.remove(\'rc-overflow-hidden\')
}
rlayerOpts.isBodyOverflow && (document.body.style.overflow = \'\')
remove()
typeof end === \'function\' && end.call(this)
}, 200);
}
// 弹框部位
auto = () => {
// ...
}
autopos = () => {
const { opened, id, fixed, follow, position } = this.state
if(!opened) return
let oL, oT
let dom = document.querySelector(\'#\' id)
let rlayero = dom.querySelector(\'.rlayer._wrap\')
if(!fixed || follow) {
rlayero.style.position = \'absolute\'
}
let area = [domUtils.client(\'width\'), domUtils.client(\'height\'), rlayero.offsetWidth, rlayero.offsetHeight]
oL = (area[0] - area[2]) / 2
oT = (area[1] - area[3]) / 2
if(follow) {
this.offset()
} else {
typeof position === \'object\' ? (
oL = parseFloat(position[0]) || 0, oT = parseFloat(position[1]) || 0
) : (
position == \'t\' ? oT = 0 :
position == \'r\' ? oL = area[0] - area[2] :
position == \'b\' ? oT = area[1] - area[3] :
position == \'l\' ? oL = 0 :
position == \'lt\' ? (oL = 0, oT = 0) :
position == \'rt\' ? (oL = area[0] - area[2], oT = 0) :
position == \'lb\' ? (oL = 0, oT = area[1] - area[3]) :
position == \'rb\' ? (oL = area[0] - area[2], oT = area[1] - area[3]) :
null
)
rlayero.style.left = parseFloat(fixed ? oL : domUtils.scroll(\'left\') oL) \'px\'
rlayero.style.top = parseFloat(fixed ? oT : domUtils.scroll(\'top\') oT) \'px\'
}
}
// 追随原素精准定位
offset = () => {
const { id, follow } = this.state
let oW, oH, pS
let dom = document.querySelector(\'#\' id)
let rlayero = dom.querySelector(\'.rlayer._wrap\')
oW = rlayero.offsetWidth
oH = rlayero.offsetHeight
pS = domUtils.getFollowRect(follow, oW, oH)
this.setState({ tipArrow: pS[2] })
rlayero.style.left = pS[0] \'px\'
rlayero.style.top = pS[1] \'px\'
}
// 利润最大化弹框
full = () => {
// ...
}
// 修复弹框
restore = () => {
const { id, maximize, rlayerOpts } = this.state
let dom = document.querySelector(\'#\' id)
let rlayero = dom.querySelector(\'.rlayer._wrap\')
let otit = dom.querySelector(\'.rlayer__wrap-tit\')
let ocnt = dom.querySelector(\'.rlayer._wrap-cntbox\')
let obtn = dom.querySelector(\'.rlayer__wrap-btns\')
let omax = dom.querySelector(\'.rlayer._maximize\')
let t = otit ? otit.offsetHeight : 0
let b = obtn ? obtn.offsetHeight : 0
if(!rlayerOpts.lockScroll) {
rlayerOpts.isBodyOverflow = false
this.setState({rlayerOpts})
document.body.style.overflow = \'\'
}
maximize && omax.classList.remove(\'maximized\')
rlayero.style.left = parseFloat(rlayerOpts.rect[0]) \'px\'
rlayero.style.top = parseFloat(rlayerOpts.rect[1]) \'px\'
rlayero.style.width = parseFloat(rlayerOpts.rect[2]) \'px\'
rlayero.style.height = parseFloat(rlayerOpts.rect[3]) \'px\'
ocnt.style.height = parseFloat(rlayerOpts.rect[3] - t - b) \'px\'
}
// 拖动|放缩弹窗
move = () => {
// ...
}
// 事故处理
callback = () => {
const { time } = this.state
// 倒数计时关掉弹窗
if(time) {
$index
// 避免反复记数
if($timer[$index] != null) clearTimeout($timer[$index])
$timer[$index] = setTimeout(() => {
this.close()
}, parseInt(time) * 1000);
}
}
// 点一下利润最大化按键
maximizeClicked = (e) => {
let o = e.target
if(o.classList.contains(\'maximized\')) {
// 修复
this.restore()
} else {
// 利润最大化
this.full()
}
}
// 点一下遮罩层
shadeClicked = () => {
if(this.state.shadeClose) {
this.close()
}
}
// 按键事情
btnClicked = (index, e) => {
let btn = this.state.btns[index]
if(!btn.disabled) {
typeof btn.click === \'function\' && btn.click(e)
}
}
}
好啦,以上便是根据React.js完成PC端弹出框部件,期待对我们有些协助哈!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。