react-router4路由切換動(dòng)畫

寫在前面

之前我寫過關(guān)于react-transition-groupreact-motion的使用教程灸蟆,就控制粒度上來說囤耳,react-motion要好很多,但是react-motion有個(gè)比較麻煩的問題,就是我暫時(shí)沒找到開箱即用的動(dòng)畫封裝亿蒸,而用react-motion也沒法使用animate.css,所以如果項(xiàng)目僅僅只用于web端掌桩,沒考慮native边锁,那么建議還是使用react-transition-group,會(huì)方便很多

用到的第三方庫

  • react-router-dom 4.2.2 用于路由
  • react-transition-group 2.2.1 用于react動(dòng)畫實(shí)現(xiàn),這里需要注意下波岛,使用的不是版本1茅坛,而是只包含{Transition, TransitionGroup, CSSTransition}的版本2
  • animate.css 用于動(dòng)畫效果

熱身

在正式開始寫路由的切換動(dòng)畫前,我們先用react-transition-group結(jié)合animate.css來實(shí)現(xiàn)一個(gè)簡單的組件進(jìn)出場(chǎng)動(dòng)畫则拷,以此回顧之前關(guān)于react-transition-group的知識(shí)
react-transition-group文檔

    <div>
        <button onClick={this.toggleState}>click</button>
        {/*第一個(gè)例子*/}
        <CSSTransition
          in={this.state.show}
          classNames={{
            enter: 'animated',
            enterActive: 'bounceIn',
            exit: 'animated',
            exitActive: 'bounceOut'
          }}
          timeout={500}
          mountOnEnter={true}
          unmountOnExit={true}
        >
          <div className="box" />
        </CSSTransition>
      </div>

效果

demo1.gif

代碼很簡單贡蓖,用in控制組件的顯示和隱藏曹鸠,用classNames控制組件進(jìn)出場(chǎng)的className,稍微需要注意的是與animate.css的結(jié)合方式

路由切換

回顧了組件的進(jìn)場(chǎng)和出場(chǎng)動(dòng)畫實(shí)現(xiàn)后斥铺,我們正式來開始寫路由的切換動(dòng)畫彻桃。先理清楚思路,在react-router4里面晾蜘,每個(gè)路由對(duì)應(yīng)其實(shí)就是一個(gè)組件邻眷,無非就是在路由匹配到的時(shí)候,將CSSTransitionin設(shè)置為true剔交,不匹配設(shè)置為false肆饶,僅此而已。
唯一麻煩的地方在于怎么獲取路由的匹配信息省容,翻看react-router4的api,我們看到,Route和渲染有關(guān)的props有三個(gè),component,render,children,componentrender都拿不到匹配信息抖拴,只要路由匹配到,組件就會(huì)mount,反之腥椒,就會(huì)unmount阿宅,我們無法進(jìn)行控制,而children正好符合我們的期望笼蛛,它與render類似洒放,不同的地方在于無論path是否匹配,都會(huì)被觸發(fā)滨砍,然后會(huì)將當(dāng)前的match信息傳遞過來往湿,我們也正好可以通過match來控制CSSTransition

先寫一個(gè)無動(dòng)畫的路由切換

不管怎么樣,我們先寫個(gè)簡單的路由切換惋戏,然后再對(duì)其進(jìn)行改裝

主路由

<Router>
        <div className="router4-transition">
          <div className="nav">
            <NavLink to="/" exact className="nav-item" activeClassName="active">
              home
            </NavLink>
            <NavLink to="/page1" className="nav-item" activeClassName="active">
              page1
            </NavLink>
            <NavLink to="/page2" className="nav-item" activeClassName="active">
              page2
            </NavLink>
          </div>

          <div className="pages">
            <Route
              path="/"
              exact
              component={props => {
                if(!props.match) return null
                return <Index />
              }}
            />
            <Route
              path="/page1"
              children={props => {
                if(!props.match) return null
                return <Page1 />
              }}
            />
            <Route
              path="/page2"
              children={props => {
                if(!props.match) return null
                return <Page2 />
              }}
            />
          </div>
        </div>
      </Router>

Index

class Index extends Component {
    render() {
      return <div className="page index">index</div>
    }
  }

Page1

class Page1 extends Component {
    render() {
      return <div className="page page1">page1</div>
    }
  }

Page2

class Page2 extends Component {
    render() {
      return <div className="page page2">page2</div>
    }
  }

簡單的路由就寫好了领追,接下來考慮加動(dòng)畫

利用高階組件給頁面加上動(dòng)畫

我并不希望在頁面內(nèi)部實(shí)現(xiàn)動(dòng)畫邏輯,首先是頁面邏輯與動(dòng)畫邏輯無關(guān)响逢,其次如果每寫一個(gè)頁面就寫一次動(dòng)畫邏輯绒窑,我怕是要累死,所以我們這里將動(dòng)畫邏輯單獨(dú)抽取出來舔亭,封裝成一個(gè)高階組件

function wrapAnimation(WrappedComponent) {
  return class extends Component {
    render() {
      return (
        <CSSTransition
          in={this.props.match !== null}
          classNames={{
            enter: 'animated',
            enterActive: 'fadeInDown',
            exit: 'animated',
            exitActive: 'fadeOutDown'
          }}
          timeout={1000}
          mountOnEnter={true}
          unmountOnExit={true}
        >
          <WrappedComponent {...this.props} />
        </CSSTransition>
      )
    }
  }
}

也是沒啥可講的代碼些膨,接下來,我們將我們的頁面Index, Page1, Page2外面套一層高階組件

const Index = wrapAnimation(
  class Index extends Component {
    render() {
      return <div className="page index">index</div>
    }
  }
)

const Page1 = wrapAnimation(
  class Page1 extends Component {
    render() {
      return <div className="page page1">page1</div>
    }
  }
)

const Page2 = wrapAnimation(
  class Page2 extends Component {
    render() {
      return <div className="page page2">page2</div>
    }
  }
)

ok钦铺,然后再稍微修改下我們的路由層

<Router>
        <div className="router4-transition">
          <div className="nav">
            <NavLink to="/" exact className="nav-item" activeClassName="active">
              home
            </NavLink>
            <NavLink to="/page1" className="nav-item" activeClassName="active">
              page1
            </NavLink>
            <NavLink to="/page2" className="nav-item" activeClassName="active">
              page2
            </NavLink>
          </div>

          <div className="pages">
            <Route
              path="/"
              exact
              children={props => {
                return <Index {...props} />
              }}
            />
            <Route
              path="/page1"
              children={props => {
                return <Page1 {...props} />
              }}
            />
            <Route
              path="/page2"
              children={props => {
                return <Page2 {...props} />
              }}
            />
          </div>
        </div>
      </Router>

接下來订雾,直接看效果吧


router4-transition.gif

總結(jié)

和普通的組件切換動(dòng)畫差不多,只是需要注意下怎么在react-router4的路由中獲取組件的顯示狀態(tài)

完整的代碼我放到了github上: https://github.com/soyal/router4-transition

感謝你的閱讀

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末矛洞,一起剝皮案震驚了整個(gè)濱河市洼哎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖谱净,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窑邦,死亡現(xiàn)場(chǎng)離奇詭異擅威,居然都是意外死亡壕探,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門郊丛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來李请,“玉大人,你說我怎么就攤上這事厉熟〉贾眩” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵揍瑟,是天一觀的道長白翻。 經(jīng)常有香客問我,道長绢片,這世上最難降的妖魔是什么滤馍? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮底循,結(jié)果婚禮上巢株,老公的妹妹穿的比我還像新娘。我一直安慰自己熙涤,他們只是感情好阁苞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著祠挫,像睡著了一般那槽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上等舔,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天骚灸,我揣著相機(jī)與錄音,去河邊找鬼软瞎。 笑死逢唤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的涤浇。 我是一名探鬼主播鳖藕,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼只锭!你這毒婦竟也來了著恩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎喉誊,沒想到半個(gè)月后邀摆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡伍茄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年栋盹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敷矫。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡例获,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出曹仗,到底是詐尸還是另有隱情榨汤,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布怎茫,位于F島的核電站收壕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏轨蛤。R本人自食惡果不足惜蜜宪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望俱萍。 院中可真熱鬧端壳,春花似錦、人聲如沸枪蘑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岳颇。三九已至照捡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間话侧,已是汗流浹背栗精。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞻鹏,地道東北人悲立。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像新博,于是被迫代替她去往敵國和親薪夕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,077評(píng)論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫赫悄、插件原献、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,094評(píng)論 4 62
  • Serialization解析 添加如下引用 序列化 反序列化 Newtonsoft解析 添加引用通過NuGet引...
    ChainZhang閱讀 4,693評(píng)論 0 4
  • 1馏慨、美觀大方、可嵌入或擺放桌面使用 2姑隅、支持快充写隶、充電快、不發(fā)燙讲仰、聲音提示慕趴、安全可靠 3、集成過壓叮盘、過流秩贰、過溫保護(hù)...
    手機(jī)車載無線充電器閱讀 279評(píng)論 0 0
  • “爸爸,我今天數(shù)學(xué)考試得了第一名柔吼!”兒子興沖沖的推開門,人還沒到家丙唧,話已傳出很遠(yuǎn)了愈魏。 兒子也不等爸爸回答,又接著說...
    萍易近人閱讀 376評(píng)論 0 0