一、背景
众所周知,产品经理有三宝:弹窗、浮层和引导。身为一个程序员,尤其是前端工程师不得不面向产品编程,由于原型图上满满的弹窗,逼迫我们不得不封装一个弹窗组件来应付产品的需求
二、需要实现的Modal组件的API
1、通过传入一个visible来控制弹框的显示与隐藏,数据类型为boolean
2、通过传入一个title来设置弹框的标题,数据类型为string
3、通过传入一个onOk函数来设置弹框确认按钮的操作,数据类型为function
4、通过传入一个onCancel函数来设置弹框关闭取消按钮的操作,数据类型为function
5、通过传入一个children来设置弹框主体内容,数据类型为element
三、Modal组件具体代码实现
import React, { Component } from 'react'
import Button from '../Button/Button'
import PropTypes from 'prop-types'
import './GYModal.less'
export default class GYModal extends Component {
static propTypes = {
visible: PropTypes.bool,
title: PropTypes.string,
onOk: PropTypes.func,
onCancel: PropTypes.func,
children: PropTypes.element
}
static defaultProps = {
visible: false,
title: '标题',
onOk: () => {},
onCancel: () => {}
}
render () {
const {
visible,
title,
children,
onOk,
onCancel
} = this.props,
show = { zIndex: 2000, opacity: 1 },
hide = { zIndex: -1, opacity: 0 },
contShow = { width: '600px', height: '600px' },
contHide = { width: '0px', height: '0px' }
return (
<div className="gy-modalContainer" style={ visible ? show : hide }>
<div className="mask" onClick={onCancel}></div>
<div className="innerContent" style={ visible ? contShow : contHide }>
<div className="innerContent-header">
<div className="innerContent-title">{title}</div>
</div>
<div className="innerContent-center">
{children}
</div>
<div className="innerContent-footer">
<Button type='cancel' onClick={onCancel}>取消</Button>
<Button type='primary' onClick={onOk}>确定</Button>
</div>
</div>
</div>
)
}}注意:这里在打开和关闭弹框时,增加了css3动画过滤效果。一开始为了实现动画过渡效果,我首先想到的是通过改变display: none到display: block,并且设置transition: all .3s ease来实现过滤动画效果,后来发现根本没有效果,原因是transition是不支持display属性的过渡的,当然你可以通过js的settimeout来实现,这边就直接用css3来实现动画过渡效果了。Modal组件最外层容器通过改变z-index和opacity来实现过渡动画效果,而Modal组件的弹框内容部分主要是通过改变弹框的width和height来实现过渡动画效果的,这两个部分的动画效果都是由visible来控制的。
.gy-modalContainer{
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 1;
transition: all .3s cubic-bezier(.075, .82, .165, 1);
z-index: -1;
.mask{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 2;
background-color: rgba(0,0,0,.3);
}
.innerContent{
position: absolute;
left: 50%;
top: 50%;
width: 600px;
height: 600px;
height: auto;
z-index: 3;
background-color: #FFFFFF;
transition: all .3s cubic-bezier(.075, .82, .165, 1);
transform-origin: 75.5px 221.5px 0px;
transform: translate(-50%,-50%);
border-radius: 4px;
.innerContent-header{
padding: 13px 16px;
border-radius: 4px 4px 0 0;
background: #fff;
color: rgba(0,0,0,.65);
border-bottom: 1px solid #e9e9e9;
.innerContent-title{
margin: 0;
font-size: 14px;
line-height: 21px;
font-weight: 500;
color: rgba(0,0,0,.85);
}
}
.innerContent-center{
padding: 16px;
font-size: 12px;
line-height: 1.5;
}
.innerContent-footer{
border-top: 1px solid #e9e9e9;
padding: 10px 16px 10px 10px;
border-radius: 0 0 4px 4px;
display: flex;
align-items: center;
justify-content: flex-end;
}
}}四、使用Modal组件
以下是render函数中的代码
以下是展示效果