React Modal 的一种粗暴实现

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

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

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值