React Modal 的一种粗暴实现

来源:互联网 发布:人工智能与信贷的结合 编辑:程序博客网 时间:2024/05/10 20:21

React Modal 的一种粗暴实现

modal什么的很好做不就是个bool吗,要么显示要么隐藏。

一开始这个modal很简单,

const modal =(isShow)=><div style={{display:isShow?"block":"none"}}>Balbala</div>

但是这个样子的modal很突兀,很粗暴,连你自己也忍不住想加一个fade动画的吧。

在jquery里面那是相当好用,一个接口就搞定了。

fade-out;fade-in用css实现,很常规。

在react里面怎么实现呢。

本文来讲一讲对于modal 的一种粗暴的解决方案,带fadeIn fadeOut动画解决方案。

@-webkit-keyframes fadeIn {  from {    opacity: 0;  }  to {    opacity: 1;  }}@keyframes fadeIn {  from {    opacity: 0;  }  to {    opacity: 1;  }}.fade-in {  -webkit-animation: fadeIn ease .3s forwards;          animation: fadeIn ease .3s forwards;}@-webkit-keyframes fadeOut {  from {    opacity: 1;  }  to {    opacity: 0;  }}@keyframes fadeOut {  from {    opacity: 1;  }  to {    opacity: 0;  }}.fade-out {  -webkit-animation: fadeOut ease .3s forwards;          animation: fadeOut ease .3s forwards;}.modal.fade-out{    pointer-events: none;}

在使用react的时候将你的modal放在父级组件的时候:

  1. 通过props提供接口访问。至少需要两个接口,一个bool变量用来控制是否显示,一个关闭的回调函数用来改变它的状态:bool isVisible,void onClose()

  2. 除了通过接口的方法控制以外,还可以使用ref。 在modal内部实现显示隐藏的逻辑。然后ref到组件实例,至少需要两个接口void show();void hide(),然而这种方式实现起来的缺陷就是,每次使用的时候得先ref到组件的实例;这种写法自身需要维护自己的显示隐藏状态。

在生命周期 componentWillMount时判断初始状态是否为显示。如果初始状态为不显示,则延迟挂载,防止fadeIn动画闪烁的副作用。

如果一开始modal就是不可见状态的话,modal在挂载的时候会fadeOut一下,那么你就会看见在视图上你的弹窗突然一下消失。实际上,我们并不想让它发生消失这件事。因为一开始的时候他是藏起来的就可以了。然而fadeoout这类的动画它是把opacity从1变到0;

所以我们不得不需要一个状态 hide 在一开始的时候将自己设置为hide,在props发生改变的时候对modal的显示和隐藏状态作出改变。并且至此以后再也不需要这个hide了。因为model已经进入了。

将真实render在componentWillReceiveProps中判断好逻辑后再显示出来。

class Modal extends Component {    constructor(props){        super(props);        this.isFixed = false;    }    componentWillMount(){        console.log(this.props);        /*         * 初始状态为false的情况下,默认不可见;         * 为防止fadeOut触发,做以下操作。         * */        if( this.props.visible ){            this.isFixed = true;            this.render    = this.renderCurrent;        }    }    componentWillReceiveProps(np){        /*        * magic        */        if( this.props.visible !== np.visible ){            if( !this.isFixed ){                this.render    = this.renderCurrent;                this.isFixed = true;            }        }    }    renderCurrent(){        const { visible,onClose } = this.props;        return <div onClick={onClose}                    className={visible ? "modal fade-in" : "modal fade-out"}>            <div className="content">                <div>BALABALABLA</div>            </div>        </div>    }    render(){        return <div/>    }}

在组件的上下文通过成员变量isFixed 来判断是不是已经完成了我们的modal fix行为。

因为js的灵活性,这样实现起来是没有问题的,对于性能来说,也没有问题。

如果你要快速实现一个modal,并要求能够有fadeIn,fadeOut 这种过度下过的话。
这个是来的最简单的方式了。

在antd中,实现modal通过在React的RootNode createClass完成。
当第一次render的时候,如果你的modal是不显示的话,它在Dom里面其实就是个


当props发生有关isVisible的变化的时候,才真正的渲染了modal的dom结构。isVisible再次变化为false的时候,dom结构还是modal的dom结构,改变的只是一个fade类名。

如果不使用第三方框架。强烈建议这种野路子的写法。

当然,你还需要一个wrap层,弄成fixed的,然后你的modal窗体应该是absolute的,通过margin调整位置。给你的wrap在设置一个rgba的浅黑色背景,然后再在wrap上增加点击效果,使它可以点击遮罩关闭。

当然这个时候你又遇到了另一个新问题

因为事件传递,你又到modal的事件handle里加上了preventDefault。

到此 基本上实现了一个可以用的modal 了。

另外的,给这个modal增加一些新的props,像增加一些诸如 title啊content啊 contentGetter啊这种东西,哇晒可以复用了。

当然,fadeout之外也可以使用slide,flip, scale,boom等。

那么如何实现 在函数内部调用一个方法来显示一个modal呢。

比如:

handleBtnClick(){    modal.info("hello");    modal.confirm({        title:"dasd",        content:"dasdas",        onOk(){},        onCancel(){}    })    modal.modal(reactElement)    modal.warning({    })}

这种写法也是很风骚,那么怎么实现呢。下次再说啊。

原创粉丝点击