这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战
TIP 👉 不畏浮云遮望眼,只缘身在最高层。——王安石《登飞来峰》
前言
Web Component是前端界一直非常热衷的一个领域,用第三方组件化的框架去实现的话,你需要依赖框架本身很多东西,很多时候我们只是简单的几个组件,不是很大,也不是很多,所以为了保证组件的`轻量,简单`,其实这个时候我们并不想采用第三方的框架。Modal 模态对话框
import
import Modal from '@/components/Modal/Modal';
Props
1. visible
-
类型:bool
-
默认值:false
-
说明:是否可见, true表示可见
2. type
-
类型:string
-
默认值:无
-
说明:类型
3. width
-
类型:string|number
-
默认值:520
-
说明:宽度
4. title
-
类型:string|ReactNode
-
默认值:无
-
说明:标题
5. children
-
类型:string|ReactNode
-
默认值:无
-
说明:主体
6. header
-
类型:string|ReactNode
-
默认值:无
-
说明:头部
-
不传值,显示默认头部; 传节点,自定义头部内容;传null,不显示头部;
7. footer
-
类型:string|ReactNode
-
默认值:无
-
说明:底部
-
不传值,显示默认底部; 传节点,自定义底部内容;传null,不显示底部;
8. okText
-
类型:string
-
默认值:确认
-
说明:确认按钮文字
9. cancelText
-
类型:string
-
默认值:取消
-
说明:取消按钮文字
10. picPath
-
类型:string|ReactNode
-
默认值:无
-
说明:图片路径
11. style
-
类型:object
-
默认值:无
-
说明:设置浮层的样式
12. centered
-
类型:bool
-
默认值:false
-
说明:垂直居中展示 Modal
实现一款Modal.js
import React from 'react';
import PropTypes from 'prop-types';
import { createPortal } from 'react-dom';
const classNames = require('classnames');
import Button from '../../components/Button/Button.js';
import './Modal.scss';
/**
* Modal 模态对话框
*/
class Modal extends React.Component {
// 入参类型检查
static propTypes = {
// 是否可见(true表示可见)
visible: PropTypes.bool,
// 类型
type: PropTypes.string,
// 宽度
width: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),
// 确认按钮回调函数
onOk: PropTypes.func,
// 关闭按钮回调函数
onCancel: PropTypes.func,
// 确认按钮文案
okText: PropTypes.string,
// 关闭按钮文案
cancelText: PropTypes.string,
// 点击蒙层是否允许关闭
maskClosable: PropTypes.bool,
// 头部内容,当不需要默认头部时,可以设为 header={null}
header: PropTypes.node,
// 底部内容,当不需要默认底部按钮时,可以设为 footer={null}
footer: PropTypes.node,
// 可用于设置浮层的样式,调整浮层位置等
style: PropTypes.object,
// 是否垂直居中显示(true表示居中显示)
centered: PropTypes.bool,
};
// 入参默认值
static defaultProps = {
visible: false,
type: '',
width: '480',
onOk: () => {},
onCancel: () => {},
okText: '确认',
cancelText: '取消',
maskClosable: true,
centered: false,
prefixCls: 'modal',
}
constructor(props) {
super(props);
this.handleOk = this.handleOk.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.node = document.createElement('div');
// this.node.className = 'modal-div';
document.body.appendChild(this.node);
}
componentWillReceiveProps(props) {
// console.log(props);
}
// 点击确认,更新modal中的 visible 状态
handleOk() {
const { onOk } = this.props;
onOk && onOk();
}
// 点击取消,更新modal中的 visible 状态
handleCancel() {
const { onCancel } = this.props;
onCancel && onCancel();
}
render() {
const {
visible,
type,
width,
title,
children,
header,
footer,
okText,
cancelText,
picPath,
style,
centered,
prefixCls
} = this.props;
var modalClass = classNames(prefixCls, {
[`${prefixCls}-${type}`]: type
}),
iconClass1 = classNames('icon', {
[`icon-${type}`]: type
});
let iconClass2 = '';
switch (type) {
case 'confirm':
iconClass2 = 'icon-bangzhu';
break;
case 'info':
iconClass2 = 'icon-xinxi-xianxing';
break;
case 'success':
iconClass2 = 'icon-jieguoye';
break;
case 'error':
iconClass2 = 'icon-guanbishibaixianxing';
break;
case 'warning':
iconClass2 = 'icon-xinxi-xianxing';
break;
default:
break;
}
const defaultHeader = (
<div className="modal-header">
<div className="modal-title">{title}</div>
</div>
);
const defaultFooter = (
<div className="modal-footer">
<Button type="plain" onClick={this.handleCancel}>{cancelText}</Button>
<Button type="primary" onClick={this.handleOk}>{okText}</Button>
</div>
);
if (!visible) {
return null;
}
return (
createPortal(
<div className="modal-root">
<div className="modal-mask" onClick={this.props.maskClosable ? this.handleCancel : () => {}}></div>
<div className={`modal-wrap ${!!centered ? "modal-centered" : ""}`}>
<div className={modalClass} style={{...style, ...{width: parseFloat(width)+'px'}}}>
<div className="modal-content">
{
!type && (
<div className="modal-close" onClick={this.handleCancel}>
<i className="icon icon-guanbi-xiao"></i>
</div>
)
}
{!type && header === undefined ? defaultHeader : header}
<div className="modal-body">
{!type && children}
{
type && (
<div className={`modal-confirm-${type}`}>
<div className="modal-confirm-body">
<div className="modal-confirm-title">
<i className={`${iconClass1} ${iconClass2}`}></i>{title}
</div>
<div className="modal-confirm-content">{children}</div>
</div>
<div className="modal-confirm-btns">
{type == "confirm" && (<Button type="plain" onClick={this.handleCancel}>{cancelText}</Button>)}
<Button type="primary" onClick={this.handleOk}>{okText}</Button>
</div>
</div>
)
}
{type == "picview" && (<img src={picPath} />)}
</div>
{!type && footer === undefined ? defaultFooter : footer}
</div>
</div>
</div>
</div>, //塞进传送门的JSX
this.node //传送门的另一端DOM node
)
);
}
}
export default Modal;
「欢迎在评论区讨论」