成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

項目實踐:從react-router v3遷移到v4

zhangrxiang / 1494人閱讀

摘要:詳見對綁定監(jiān)聽事件,把的改變同步到的中用來把的更新同步到中。代碼分割版本通過和實現(xiàn)代碼分割和動態(tài)路由。筆者認為,更符合的組件思想,于是做了一個實踐。

原文:https://github.com/YutHelloWo...

前言

今年3月初發(fā)布了react-router v4,相較之前的v3和v2版本做了一個破壞性的升級。遵循一切皆React Component的理念。靜態(tài)路由變成了動態(tài)路由。這里記錄下v3項目如何遷移到v4。
項目地址:https://github.com/YutHelloWo...

遷移步驟

對React-Router和Redux同步進行重構(gòu)

重寫路由

代碼分割

瑣碎的API替換

詳細代碼參閱這個PR

React-Router和Redux同步

這里我們?nèi)匀徊皇褂?b>react-router-redux這個庫。為了和react-routerv4版本保持一致,react-router-redux發(fā)布了v5.0.0版本,你當(dāng)然也可以使用它來實現(xiàn)這個功能。

1. 替換依賴包

v3我們引入的是react-router包,在v4我們只引入react-router-dom這個包。安裝react-router-dom時會同時安裝history。

package.json

-    "react-router": "^3.0.0",
+    "react-router-dom": "^4.1.2",
2. 改寫對browserHistory的創(chuàng)建和當(dāng)前l(fā)ocation的獲取

location.js

// v3
import { browserHistory } from "react-router"

// 獲取當(dāng)前l(fā)ocation
const initialState = browserHistory.getCurrentLocation()

==>

// v4
import createHistory from "history/createBrowserHistory"

export const history = createHistory()

// Get the current location.
const initialState = history.location

這里替換的是history,和當(dāng)前l(fā)ocation的獲取方法。在v3,browserHistory存在于react-router中,而v4把history抽離了出來,提供了createBrowserHistory ,createHashHistory ,createMemoryHistory 三種創(chuàng)建history的方法。v4中創(chuàng)建的history導(dǎo)出,在后面會需要用到。

history API詳見: https://github.com/ReactTrain...

3. 對history綁定監(jiān)聽事件,把location的改變同步到Redux的store中

createStore

// v3
import { browserHistory } from "react-router"
import { updateLocation } from "./location"

store.unsubscribeHistory = browserHistory.listen(updateLocation(store))

updateLocation用來把location的更新同步到store中。

export const updateLocation = ({ dispatch }) => {
  return (nextLocation) => dispatch(locationChange(nextLocation))
}

一切似乎都很順利,接著第一個坑來了

根據(jù)historyAPI提供的

// Listen for changes to the current location.
const unlisten = history.listen((location, action) => {
  // location is an object like window.location
  console.log(action, location.pathname, location.state)
})

修改createStore.js

==>

// v4
import { updateLocation, history } from "./location"

// 監(jiān)聽瀏覽器history變化,綁定到store。取消監(jiān)聽直接調(diào)用store.unsubscribeHistory()
store.unsubscribeHistory = history.listen(updateLocation(store))

接著修改app.js

// v3
// ...
import { browserHistory, Router } from "react-router"

// ...

==>

// ...
import {  BrowserRouter, Route } from "react-router-dom"

// ...

  
//...

我們到瀏覽器中查看,發(fā)現(xiàn)URL變化并沒有觸發(fā)updateLocation(store),state并沒有變化。

What a f**k!
問題出在BrowserRouter在創(chuàng)建的時候在內(nèi)部已經(jīng)引入了一個historyupdateLocation(store)應(yīng)該監(jiān)聽的是內(nèi)部的這個history。這里貼下BrowserRouter.js的代碼

import React from "react"
import PropTypes from "prop-types"
import createHistory from "history/createBrowserHistory"
import { Router } from "react-router"

/**
 * The public API for a  that uses HTML5 history.
 */
class BrowserRouter extends React.Component {
  static propTypes = {
    basename: PropTypes.string,
    forceRefresh: PropTypes.bool,
    getUserConfirmation: PropTypes.func,
    keyLength: PropTypes.number,
    children: PropTypes.node
  }

  history = createHistory(this.props)

  render() {
    return 
  }
}

export default BrowserRouter

于是,我們放棄使用BrowserRouter,而使用Router

修改app.js

==>

// v4
import { Router, Route } from "react-router-dom"
//...


  

這樣,這個坑算是填上了。也就完成了history和store之間的同步。

重寫路由

v4取消了PlainRoute 中心化配置路由。Route是一個react component。
取消了IndexRoute,通過Switch來組件提供了相似的功能,當(dāng)被渲染時,它僅會渲染與當(dāng)前路徑匹配的第一個子。

routes/index.js

// v3
//..
export const createRoutes = (store) => ({
  path        : "/",
  component   : CoreLayout,
  indexRoute  : Home,
  childRoutes : [
    CounterRoute(store),
    ZenRoute(store),
    ElapseRoute(store),
    RouteRoute(store),
    PageNotFound(),
    Redirect
  ]
})
//...

==>

// ...
const Routes = () => (
  
    
    
    
    
    
    
    
  
)

export default Routes
//

這里路由的定義方式由PlainRoute Object改寫成了組件嵌套形式,在PageLayout.js中插入

代碼分割

v3版本通過getComponetrequire.ensure實現(xiàn)代碼分割和動態(tài)路由。在v4版本,我們新增異步高階組件,并使用import()替代require.ensure()

Counter/index.js

// v3
import { injectReducer } from "../../store/reducers"

export default (store) => ({
  path : "counter",
  /*  動態(tài)路由 */
  getComponent (nextState, cb) {
    /* 代碼分割 */
    require.ensure([], (require) => {
      const Counter = require("./containers/CounterContainer").default
      const reducer = require("./modules/counter").default

      /*  將counterReducer注入rootReducer  */
      injectReducer(store, { key : "counter", reducer })

      cb(null, Counter)
    }, "counter")
  }
})

首先,新增AsyncComponent.js

import React from "react"

export default function asyncComponent (importComponent) {
  class AsyncComponent extends React.Component {
    constructor (props) {
      super(props)

      this.state = {
        component: null,
      }
    }

    async componentDidMount () {
      const { default : component } = await importComponent()

      this.setState({
        component: component
      })
    }

    render () {
      const C = this.state.component

      return C
        ? 
        : null
    }
  }

  return AsyncComponent
}

這個asyncComponent 函數(shù)接受一個importComponent 的參數(shù),importComponent 調(diào)用時候?qū)討B(tài)引入給定的組件。

componentDidMount 我們只是簡單地調(diào)用importComponent 函數(shù),并將動態(tài)加載的組件保存在狀態(tài)中。

最后,如果完成渲染,我們有條件地提供組件。在這里我們?nèi)绻粚憂ull的話,也可提供一個菊花圖,代表著組件正在渲染。

接著,改寫Counter/index.js

==>

import { injectReducer } from "../../store/reducers"
import { store } from "../../main"
import Counter from "./containers/CounterContainer"
import reducer from "./modules/counter"

injectReducer(store, { key : "counter", reducer })

export default Counter

一旦加載Counter/index.js,就會把counterReducer注入到Rudecer中,并加載Counter組件。

瑣碎API的替換

v4 移除了onEnter onLeave等屬性,history替換router屬性,新增match

this.props.router.push("/")

==>

this.props.history.push("/")
this.props.params.id

==>

this.props.match.params.id
總結(jié)

這里可以看出,使用v4替換v3,對于大型項目并不是一件輕松的事情,有許多小坑要踩,這就是社區(qū)很多項目仍然使用v2/v3的原因。筆者認為,v4更符合React的組件思想,于是做了一個實踐。最后歡迎指正拍磚,捂臉求star ? 。

參考

Code Splitting in Create React App

Migrating from v2/v3 to v4

React-Router

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/84747.html

相關(guān)文章

  • ReactRouter升級 v2 to v4

    摘要:概述相對于幾乎是重寫了新版的更偏向于組件化。汲取了很多思想,路由即是組件,使路由更具聲明式,且方便組合。如果你習(xí)慣使用,那么一定會很快上手新版的。被一分為三。不止是否有意義參考資料遷移到關(guān)注點官方文檔 概述 react-router V4 相對于react-router V2 or V3 幾乎是重寫了, 新版的react-router更偏向于組件化(everything is comp...

    JasonZhang 評論0 收藏0
  • react-router 升級小記

    摘要:前言最近將公司項目的從版本升到了版本,跟完全不兼容,是一次徹底的重寫。升級過程中踩了不少的坑,也有一些值得分享的點。沒有就會匹配所有路由最后不得不說升級很困難,坑也很多。 前言 最近將公司項目的 react-router 從 v3 版本升到了 v4 版本,react-router v4 跟 v3 完全不兼容,是一次徹底的重寫。這也給升級造成了極大的困難,與其說升級不如說是對 route...

    isLishude 評論0 收藏0
  • [ 一起學(xué)React系列 -- 11 ] React-Router4 (1)

    摘要:中的包中的包主要有三個和。的理念上面提到的理念是一切皆組件以下統(tǒng)一稱組件。從這點來說的確方便了不少,也迎合一切皆組件的理念。組件是中主要的組成單位,可以認為是或的路由入口。將該標(biāo)示為嚴(yán)格匹配路由。的屬性追加一條。 2019年不知不覺已經(jīng)過去19天了,有沒有給自己做個總結(jié)?有沒有給明年做個計劃?當(dāng)然筆者已經(jīng)做好了明年的工作、學(xué)習(xí)計劃;同時也包括該系列博客剩下的博文計劃,目前還剩4篇:分別...

    tinysun1234 評論0 收藏0
  • React-router v4 路由配置方法

    摘要:使用了約等于才能匹配或者能匹配,所以說是約等于。使用了和才能匹配后續(xù)補充這是版本中新添加,主要用來做唯一匹配的功能。就是想要在眾多路由中只匹配其中一個路由。 React-Router v4 一. Switch 、Router 、Route三者的區(qū)別 1、Route Route 是建立location 和 ui的最直接聯(lián)系 2、Router react-router v4 中,Route...

    Coding01 評論0 收藏0
  • todo-list 項目問題總結(jié)(使用 react 進行開發(fā))

    摘要:項目問題總結(jié)這個項目,很簡單,前端使用,后端使用進行開發(fā)。方便移動端開發(fā)。當(dāng)動畫結(jié)束后,有一個鉤子函數(shù)可以使用其他一些功能組件,都是自己嘗試去編寫的,像日歷組件組件組件等。版本的,是沒有任何的鉤子函數(shù),我就感覺懵逼了。。。 todo-list 項目問題總結(jié) 這個 todo-list 項目,很簡單,前端使用 react,后端 nodejs 使用 koa2 進行開發(fā)。數(shù)據(jù)庫使用 Mysql...

    shengguo 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<