layer弹窗自定义html,RLayer–超赞的React.js桌面端自定义弹窗组件

今天给小伙伴们分享一个全新开发的React自定义对话框最近RLayer。

e37a7fe4afb00baf6f2dde3caa5695a6.png

7a3388c4db9445feb6ab3beab915e402.gif

看名称就能联想到前端界有名的弹窗layer.js,其实在设计开发之初就有借鉴layer插件实现思想。

bfb0d0c9ab186fa1fed7964ddf2c1e16.gif

功能

提供函数式调用方法 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: "

确认框(这里是确认框提示信息,这里确认框提示信息,这里是确认框提示信息)

",

shadeClose: false,

zIndex: 1001,

lockScroll: false,

resize: true,

dragOut: true,

btns: [

{

text: \'取消\',

click: () => {

$el.close()

}

},

{

text: \'确定\',

style: {color: \'#61dafb\'},

click: () => {

handleInfo()

}

}

]

})

}

a48fd3991f9de80b65b22fafe25368a7.png

416d1bc543dd920bdabd8e071fa991b0.png

063381f0a89f7ece386a9e0bc408148d.png

e168f3916302ca08dd03c0e24c8520e2.png

eec18114a5f7117bd2c127f971651b9d.png

deb572f0b370b63808620c497bb4dfa4.png

RLayer弹框模板

class RLayerComponent extends React.Component{

// ...

render() {

let opt = this.state

return (

<>

{/* 遮罩 */}

{ opt.shade &&

div> }

{/* 窗体 */}

{ opt.title &&

div> }

{ opt.type == \'toast\' && opt.icon ?

div> : null }

{ opt.content ?

<>

{

opt.type == \'iframe\' ?

(

iframe>

)

:

(opt.type == \'message\' || opt.type == \'notify\' || opt.type == \'popover\') ?

(

{ opt.icon && i> }

{ opt.title &&

div> }

{ typeof opt.content == \'string\' ?

div>

:

{opt.content}div>

}

div>

div>

)

:

(

typeof opt.content == \'string\' ?

(

div>)

:

opt.content

)

}

>

:

null

}

div>

{/* btns */}

{ opt.btns &&

{

opt.btns.map((btn, index) => {

return span>

})

}

div>

}

{ opt.xclose && span> }

{ opt.maximize && span> }

{ opt.resize && span> }

div>

{/* 修复拖拽卡顿 */}

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)

}

}

}

dbc7a38c758cb9382bc9d39d1a1829ee.gif

6f6e499b95caca1459c2d989f7ca42ee.gif

好了,以上就是基于React.js实现PC端弹出框组件,希望对大家有所帮助哈!

声明:本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。导航:艺宵博客 » RLayer–超赞的React.js桌面端自定义弹窗组件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值