React Modal 的一種粗暴實作
modal什麼的很好做不就是個bool嗎,要麼顯示要麼隐藏。
一開始這個modal很簡單,
但是這個樣子的modal很突兀,很粗暴,連你自己也忍不住想加一個fade動畫的吧。
在jquery裡面那是相當好用,一個接口就搞定了。
fade-out;fade-in用css實作,很正常。
在react裡面怎麼實作呢。
本文來講一講對于modal 的一種粗暴的解決方案,帶fadeIn fadeOut動畫解決方案。
@-webkit-keyframes fadeIn {
from {
opacity: ;
}
to {
opacity: ;
}
}
@keyframes fadeIn {
from {
opacity: ;
}
to {
opacity: ;
}
}
.fade-in {
-webkit-animation: fadeIn ease .s forwards;
animation: fadeIn ease .s forwards;
}
@-webkit-keyframes fadeOut {
from {
opacity: ;
}
to {
opacity: ;
}
}
@keyframes fadeOut {
from {
opacity: ;
}
to {
opacity: ;
}
}
.fade-out {
-webkit-animation: fadeOut ease .s forwards;
animation: fadeOut ease .s forwards;
}
.modal.fade-out{
pointer-events: none;
}
在使用react的時候将你的modal放在父級元件的時候:
- 通過props提供接口通路。至少需要兩個接口,一個bool變量用來控制是否顯示,一個關閉的回調函數用來改變它的狀态:
bool isVisible,void onClose()
- 除了通過接口的方法控制以外,還可以使用ref。 在modal内部實作顯示隐藏的邏輯。然後ref到元件執行個體,至少需要兩個接口
,然而這種方式實作起來的缺陷就是,每次使用的時候得先ref到元件的執行個體;這種寫法自身需要維護自己的顯示隐藏狀态。void show();void hide()
在生命周期 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({
})
}
這種寫法也是很風騷,那麼怎麼實作呢。下次再說啊。