js弹出框自定义(js实现弹出框的插件)

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

js弹出框自定义(js实现弹出框的插件)

rlayer 基于react.js开发的PC桌面端交互式弹出框组件。融合了Dialog、Message、Notification、ActionSheet、Toast、Popover、Popconfirm等多种功能。

js弹出框自定义(js实现弹出框的插件)

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

js弹出框自定义(js实现弹出框的插件)功能

  • 提供函数式调用方法 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()
                }
            }
        ]
    })
}

js弹出框自定义(js实现弹出框的插件)
js弹出框自定义(js实现弹出框的插件)
js弹出框自定义(js实现弹出框的插件)
js弹出框自定义(js实现弹出框的插件)
js弹出框自定义(js实现弹出框的插件)
js弹出框自定义(js实现弹出框的插件)

RLayer弹框模板

class RLayerComponent extends React.Component {
    // ...

    render() {
        let opt = this.state

        return (
            
            
                {/* 遮罩 */}
                { opt.shade &&  }
                {/* 窗体 */}
                
                { opt.title &&  }
                { opt.type == 'toast' && opt.icon ?  : null }
                
                    { opt.content ? 
                    
                        {
                        opt.type == 'iframe' ? 
                        (
                            
                        )
                        : 
                        (opt.type == 'message' || opt.type == 'notify' || opt.type == 'popover') ? 
                        (
                            
                            { opt.icon &&  }
                            
                                { opt.title &&  }
                                { typeof opt.content == 'string' ? 
                                
                                :
                                {opt.content}
                                }
                            
                            
                        )
                        : 
                        (
                            typeof opt.content == 'string' ? 
                            ()
                            :
                            opt.content
                        )
                        }
                    >
                    :
                    null
                    }
                
                {/* btns */}
                { opt.btns && 
                    {
                        opt.btns.map((btn, index) => {
                            return 
                        })
                    }
                    
                }
                { opt.xclose &&  }
                { opt.maximize &&  }
                { opt.resize &&  }
                
                {/* 修复拖拽卡顿 */}
                
            
            >
        )
    }
}

默认参数配置

本文转载自:https://www.gylmap.com

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)
        }
    }
}

js弹出框自定义(js实现弹出框的插件)
js弹出框自定义(js实现弹出框的插件)

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

秒鲨号所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈!本站将在三个工作日内改正。
(0)

大家都在看

  • 电瓶怎么修复(电瓶修复液是电瓶水吗)

    修复液并非“万能药水” 仅能修复特定问题 网购电瓶修复液真的能修复电瓶吗 家里的电动车续航能力下降了,怎么办?最近网上流行一种电池修复液,说是可以成功解决电池问题。有粉丝朋友私信留…

    2022年4月3日
  • 上行速度测试如何测(手把手教你测自家网速)

    我们都知道,网络对直播而言是非常重要的,如果网速慢极可能导致直播画面卡顿等问题,那么,怎样才能知道网速呢? 测试的方法很多,但是网速的影响因素非常多,任何一个测速的软件或者网站,都…

    2022年3月17日 专栏投稿
  • 微信小程序怎样做,小程序精准引流技巧

    首先,网站必须是https,否则不可以。点击申请免费ssl证书,https://freessl.cn。 第一步,注册小程序,如果有公众号且认证过了的,直接在公众号后台,点击小程序,…

    2022年5月20日
  • 怎么恢复聊天记录,两种方法教你快速恢复

    在社交为合金的当今社会,我们聊天社交都是通过微信来完成的,手机里存了大量的微信聊天记录,想要清理这些微信数据,又怕错删重要的记录怎么办呐?不要急,卓师兄教您一招! 一、怎么设置朋友…

    2022年6月28日 专栏投稿
  • 华为手机好不好(华为手机品牌分析)

    这个话题可能会存在一些争议,甚至被一些网友认为是华为的充值稿。事实上并非如此,因为最近发生在身边的一些小事,以及职敏感令我对这个问题产生了一些思考。如今手机市场已经开始进入后华为时…

    2022年7月1日 专栏投稿
  • excel怎么打不开(excel一直打不开怎么回事)

    不知道大家有没有碰到过这种情况,有时候从网站下载的Excel表格,或者是接收到了别人发给你的表格,当你在电脑上打开的时候,会弹出这样的信息:文件已损坏,无法打开。 然而在同事电脑上…

    2022年4月28日 专栏投稿
  • 液化气热水器(液化气热水器如何安装图解法)

    随着我们生活水平的提高,为了身体健康及卫生问题,越来越注重洗澡问题。那么在选购热水器后,就要考虑热水器安装的问题,今天为大家来分享一下热水器是如何安装的。 欢迎公众号“电器维修服务…

    2022年6月21日
  • 沙宣卷发棒好用吗(100%的人用过都说好爱美必备)

    每次出行都想要极力精简行李,一款便携,功能强大的造型器是必备。想打造日常发型,卷个空气刘海,急救下乱蓬蓬的头发就需要沙宣这款直卷小精灵,造型护发二合一的MINI卷发器啦! 外形: …

    2022年3月22日
  • 一坟不烧二纸(新坟三年后看后人)

    清明将至,马上到一年一度踏青祭祖的日子,上班族们也可以迎来一个小小的假期。 现如今人们也会在清明节去给已故的亲人扫墓,或者是上坟烧纸等等,不过现在的仪式相较于古代更加简略。古时候人…

    2022年6月19日 专栏投稿
  • 信用卡怎么看额度多少(信用卡额度怎么查)

    一、平安银行信用卡的种类   平安银行发行的信用卡种类有很多,且由于每位客户的需求不同,平安银行发行的卡片特色也会有所不同哦。平安银行发行的卡片中有:平安银行保险信用卡、平安车主信…

    2022年7月4日
品牌推广 在线咨询
返回顶部