React+TS免注册DOM页面dialog弹窗

背景

在日常的需求开发中我们经常需要用到弹窗,那么在我们构建弹窗时,在引用组件是都需要引入组件DOM,然后通过事件来控制组件的影藏显示,调用也不是很方便;

本组件使用事前注册DOM的方式,业务方在使用时刻直接调用暴露的方法即可,无需再引用DOM。

示例

React+TS免注册DOM页面dialog弹窗_第1张图片

组件使用示例

import newDialog from "*./components/newDialog"
newDialog.open({
    title: "退出发布",
    content: '是否需要保存草稿箱?',
    btn: [{ text: "不保存" },{ text: "保存" }],
    callback: (event)=>{
        if(event.result == 2){
            //TODO
        }else { 
            //TODO
        }
    }
});

API

参数 说明 类型 是否必填
title 弹窗标题 String
content 弹窗展示内容 String\ ReactDom
btn 弹窗按钮可配置一个或者两个 Array
callback 弹窗响应回调方法 Function

弹窗按钮说明

//弹窗按钮是json数组配置的 最多配置两个
btn: [{ text: "不保存" },{ text: "保存" }],
//每个按钮只需要配置text按钮文案即可 样式和颜色都集成到css
//如果配置一个按钮就是底部长按钮 配置两个根据配置的数组顺序从左向右展示

回调参数

//点击按钮会返回回调数据并关闭弹出
{
  result: 1/2 //返回按钮的索引值
}

完整代码

js代码newDialog.tsx

'use strict';
import './newDialog.scss';
import * as React from 'react';
import cs from "classnames";
import * as ReactDOM from 'react-dom';
import { isIphoneX } from './../../util/util';
/** 
 * @description 解决移动端滚动穿透事件 
 **/
const ModalHelper = (function (bodyCls) {
    var scrollTop;
    return {
        afterOpen: function () {
            scrollTop = document.scrollingElement.scrollTop;
            document.body.classList.add(bodyCls);
            document.body.style.top = -scrollTop + 'px';
        },
        beforeClose: function () {
            document.body.classList.remove(bodyCls);
            // scrollTop lost after set position:fixed, restore it back.
            document.scrollingElement.scrollTop = scrollTop;
        }
    };
})('modal-open');

interface IAppProps {
    title?: string;
    content?: any;
    btn?: any;
    callback?: Function;
}

interface IAppState {
    showToast?: Boolean;
    title?: string;
    content?: any;
    btn?: any;
    callback?: Function;
    isIPhoneX?: Boolean;
}
let DialogDiv;
class Dialog extends React.Component {
    constructor(props: IAppProps) {
        super(props);
        this.state = {
            showToast: true,
            isIPhoneX: false
        };
    }
    componentWillMount() {
        let isIPhoneX = isIphoneX();
        this.setState({
            isIPhoneX
        });
    }
    static open = (options) => {
        const { ...props } = options || {};
        DialogDiv = document.createElement('div');
        setTimeout(()=>{
            document.body.appendChild(DialogDiv);
            ReactDOM.render( ,DialogDiv); 
        },100);
        ModalHelper.afterOpen();
    }
    close = (param) => {
        let result = param +1;
        this.props.callback({ result: result });
        this.setState({
            showToast: false
        });
        document.body.removeChild(DialogDiv);
        ModalHelper.beforeClose();
    }
    render() {
        const { showToast, isIPhoneX } = this.state;
        const { title, content, btn } = this.props;
        let _twoBtn = btn.length > 1 ? true : false;
        return (
            
{title}
{content}
{btn.map((item, idx) => { return (
{ this.close(idx); // item.callback(); }} className={cs('dialog-btn', { margin_r: _twoBtn && idx == 0, default: _twoBtn && idx == 0 })}> {item.text}
); })}
) } } export default Dialog;

css代码newDialog.scss

$baseFontSize: 16px !default;

// pixels to rems
@function pxToRem($px) {
    @return $px / $baseFontSize * 1rem;
}

.dialog-container {

    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, .7);
    display: none;
    z-index: 9999;

    &.show {
        display: block;
    }
}

.new-dialog-box {
    width: 100%;
    min-height: pxToRem(195px);
    background: rgba(255, 255, 255, 1);
    position: absolute;
    box-sizing: border-box;
    margin: 0;
    bottom: 0;
    z-index: 9999;
    transition: all 0.3s;
    border-radius: pxToRem(8px) pxToRem(8px) 0 0;
    // display: flex;
    .dialog-title {
        font-size: pxToRem(19px);
        margin: pxToRem(25px) auto pxToRem(25px);
        text-align: center;
        font-family: PingFangSC-Medium, PingFang SC;
        font-weight: 500;
        color: rgba(51, 51, 51, 1);
        line-height: pxToRem(19px);
    }

    .dialog-content {
        padding: 0 pxToRem(25px);
        font-size: pxToRem(14px);
        font-family: PingFangSC-Regular, PingFang SC;
        color: rgba(51, 51, 51, 1);
        margin: 0 auto pxToRem(15px);
        text-align: center;
        color: rgba(0, 0, 0, 1);
        line-height: pxToRem(27px);
        min-height: pxToRem(50px);
    }

    .dialog-bottom {
        height: pxToRem(45px);
        padding: 0 pxToRem(20px);
        margin-bottom: pxToRem(15px);
        display: flex;
        &.isIPhoneX {
            margin-bottom: pxToRem(49px);
        }
    }

    .dialog-btn {
        // margin: 0 auto pxToRem(30px);
        // width: pxToRem(300px);
        flex: 1;
        height: pxToRem(45px);
        background-image: linear-gradient(-44deg, #FCAF3C 0%, #F25228 98%);
        box-shadow: 0 8px 14px 0 rgba(190,118,22,0.20);
        border-radius: pxToRem(45px);
        text-align: center;
        line-height: pxToRem(45px);
        font-size: pxToRem(15px);
        font-family: PingFangSC-Medium, PingFang SC;
        color: rgba(255, 255, 255, 1);

        &.margin_r {
            margin-right: pxToRem(24px);
        }

        &.default {
            background: #FFFFFF;
            border: 1px solid #E6E6E6;
            box-shadow: 0 10px 20px -8px rgba(173,173,173,0.30);
            border-radius: pxToRem(45px);
            font-size: pxToRem(15px);
            font-family: PingFang-SC-Medium, PingFang-SC;
            color: rgba(85, 85, 85, 1);
        }
    }
}

另外附上代码中iPhone X系列机型判断方法

export const isIphoneX = function() {
    // iPhone X、iPhone XS
    var isIPhoneX =
        /iphone/gi.test(window.navigator.userAgent) &&
        window.devicePixelRatio &&
        window.devicePixelRatio === 3 &&
        window.screen.width === 375 &&
        window.screen.height === 812;
    // iPhone XS Max
    var isIPhoneXSMax =
        /iphone/gi.test(window.navigator.userAgent) &&
        window.devicePixelRatio &&
        window.devicePixelRatio === 3 &&
        window.screen.width === 414 &&
        window.screen.height === 896;
    // iPhone XR
    var isIPhoneXR =
        /iphone/gi.test(window.navigator.userAgent) &&
        window.devicePixelRatio &&
        window.devicePixelRatio === 2 &&
        window.screen.width === 414 &&
        window.screen.height === 896;
    if (isIPhoneX || isIPhoneXSMax || isIPhoneXR) {
        return true;
    }
    return false;
}

你可能感兴趣的:(javascript,css,react.js,typescript)