React研習之旅(二):視圖控制器-路由

靜態路由or動態路由

聲明:此處的動態與靜態專指前端應用的開發領域。javascript

路由是一種URL到頁面的映射關係.html


靜態路由

靜態路由須要開發者考慮兩層:前端

  • 頁面的開發或組件和組合
  • URL路徑與組件關係的設置

靜態路由提早聲明,簡單易懂,Vue-router就是靜態路由的例子。java

動態路由

動態路由相反,將上述兩層關注合爲一體:頁面設計開發過程直接確立了URL與組件的關係,開發的樣子,決定了路由的樣子,符合了動態的理念。開發者無需額外管理與配置路徑。省心省力。react

react-router v4採用了動態路由(react有一個靜態路由包在內測中),以前版本則是靜態路由,。 須要注意的是,react-router v4裏,route也是一種組件的存在形式.git

對比一下,感覺不一樣
//static routes
const routes = [
  {
    component: Root,
    routes: [
      {
        path: "/",
        exact: true,
        component: Home
      },
      {
        path: "/child/:id",
        component: Child,
        routes: [
          {
            path: "/child/:id/grand-child",
            component: GrandChild
          }
        ]
      }
    ]
  }
];
//dynamic routes
const App = () => (
  <Router>
    <div>
      <Header />

      <Route exact path="/" component={Home} />
      <Route path="/about" component={About} />
      <Route path="/topics" component={Topics} />
    </div>
  </Router>
);
export default App;
複製代碼

react-router體系

到react-router的github官網看到這一句:github

we actually publish several packages to npm from the same codebase. 同一個代碼基項目發佈了幾個包:web

在這裏插入圖片描述
有幾個信息:

  • react-router爲核心包,其餘包依賴該包
  • 開發web項目使用react-router-dom,開發原生應用使用react-router-native
  • 靜態路由版本react-router-config,目前內測階段

所以咱們只須要關注react-router-dom便可。express

react-router-dom的幾個核心概念

react-router-dom教程網上不少,在此咱們羅列幾個比較重要或易錯的概念,若是須要詳細內容,請至:官方APInpm


BrowserRouter 與 HashRouter

有兩種路由類型:browserRouter、HashRouter

// <BrowserRouter>
http://example.com/about

// <HashRouter>
http://example.com/#/about
複製代碼

前者使用 HTML5 History API 來跟蹤路由變化。後者使用window.location.hash做爲記錄跟蹤方式 。

前者新穎美觀,須要服務端的額外支持,原理就是攔截前端的路徑請求(非功能請求),響應同一個index.html,而後瀏覽器會根據根據路徑渲染相應的視圖或頁面。舉個express的例子:

const express = require('express');
const path = require('path');
const port = process.env.PORT || 8080;
const app = express();

//加載靜態資源,dist下放build好的文件
app.use(express.static(__dirname + '/dist'))

//非功能請求統一轉到index.html
//index.html及其對應的js文件會根據React-Router規則匹配對應route
app.get('*', function (request, response){
  response.sendFile(path.resolve(__dirname, 'dist', 'index.html'))
})

app.listen(port, function () {
  console.log("server started on port " + port)
})
複製代碼

後者簡單兼容性好,不須要額外配置服務端。 須要指出的是:rowserRouter或 HashRouter必須位於路由相關組件的最外層,此處的相關組件經常使用的有:Link、Route、Switch、Redirect

路由的導航方式
  • 聲明式導航:<Link to/>標籤,或<a href="#"></a>標籤,或<Redirect to/>
  • 編程式導航(history方法調用,須要經過):push(path)、replace(path)、go(n) 、goBack() 、 goForward()
  • withRouter高階組件,實現編程導航必須藉助withRouter高階組件
視圖/組件的配置方式

都是經過Route組件這座橋樑實施的,但有多種實施方式render、component、children

  • render只能爲函數組件,匿名、不匿名皆可.
  • children可爲函數組件、jsx對象
  • component可爲函數組件或class組件

很差理解?代碼演示對比下

function fnComponent(){
	return <div>我是個具名函數組件</div>
}
class classComponent extends Component{
	render(){
		<div>我是個class組件</div> } } //render只能爲函數組件 <Route path="/render" render={()=>{<div>我是個匿名/行內函數組件</div>}}/>
<Route path="/render" render={fnComponent}/>

//children能夠爲函數組件、也但是jsx對象
<Route path="/children" children={()=>{<div>我是個匿名/行內函數組件</div>}}/>
<Route path="/children" children={fnComponent}/>
<Route path="/children" children={<div>我是一條jsx語法標籤對象</div>}/>

//component只能爲函數組件或class組件
<Route path="/children" component={()=>{<div>我是個匿名/行內函數組件</div>}}/>
<Route path="/children" component={fnComponent}/>
<Route path="/children" component={classComponent }/>
複製代碼

注意官方有這句提示: if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render or the children prop . 翻譯就是:行內函數(匿名函數)做爲component屬性傳遞(prop)時,會在每次渲染時建立一個react元素,這將從新掛載(mount)組件,而不是在既存的基礎上更新。

這很好理解,匿名函數飄忽不定,每次render都意味着props的改變。若是實在用匿名函數,請選擇children或render的方式


再來張思惟導圖

路由思惟導圖


小結

本文介紹了React-router的一些概念,談了動態靜態路由,react-router的體系,兩種路由模式,導航方式、視圖組件配置方式,內容有深有淺,紕漏在所不免,不足之處望讀者朋友們留言或指正,謝謝!。

下一篇咱們會介紹React的打包相關

相關文章
相關標籤/搜索