初探React-router實現導航

           好久都沒有寫博客了,一是因爲最近工作也比較繁雜,二是在學習路由的時候卡了一下殼,三是工作找不到很是鬱悶。經過一段時間的嘗試,終於在學習的過程中邁出了一小步,實現了自己當初訂的一個小需求。由於還在學習過程中,就只是先拿出一點實際的效果和中間遇到的一些困難。(用react-router實現導航)



github:https://github.com/liuzaijiang/React-Router-Demo (這個是我們自己參考網上的Demo然後自己實現的一個路由導航實例)

參考的Demo:https://github.com/reactjs/react-router-tutorial/tree/master/lessons/08-index-routes

路由的基礎知識:http://www.ruanyifeng.com/blog/2016/05/react_router.html?utm_source=tool.lu(阮一峯的入門博客)


我眼中的路由:

       我目前接觸到的路由一般都是用來做導航欄,選項卡之類的功能;我就類比一下用jq的方法去實現這樣一個功能的:大體思路就是先把所有的導航和導航對應的顯示內容寫好,然後全部隱藏,最後根據點擊的那個導航,來相應的顯示那一塊內容(導航和內容一一對應)

       把這個思路用到react 中去也是可以的,相應的內容就是我們的組件,我們可以根據點擊某個導航來選擇渲染哪一個組件;這

裏其實就可以看到react的優勢,不顯示的內容不存在於DOM節點中,而用傳統的方法的話,不顯示的內容只是display:none而

已,這樣來說當你切換導航的時候就免去了不必要的重繪和重排;

       當然,reacr-router也是解決這個的方法之一,我說一下我個人第一次用完後覺得它好的地方:

******************************************************************************************************************************

      1. 首先它不用去判斷渲染哪個組件,它只需要爲每個組件定義好一個path屬性,爲每個導航欄定義好to屬性,指向我們需要顯

示的組件的path屬性,點擊相應的導航欄即顯示相應組件(其實就是<a>標籤的效果,不過react-router是用<Link>這個標籤代替

了<a>標籤的作用),這樣我們不用去爲每個導航欄去綁定事件。

      2.然後<Link>本身有一個activeClassName這個屬性,這個屬性的好處就是爲我們當前點擊的導航欄增加樣式,這個真的是真

心棒的,如果要我們自己動手去實現這個你或許還需要爲獲取當前是哪個導航欄被點擊花一點功夫去寫代碼,這裏我們直接拿來用

就好了。

      3.最後,如果我們訪問點擊了一個頁面的一個導航內容,刷新之後頁面還是會顯示之前的導航內容,如果是不用路由的方法頁

面是會顯示默認的導航內容的;這個是因爲使用路由後,頁面顯示的相應內容會在url中有具體的體現,比如我要看a內容,則是

http://www.this-is-a-spa.com/a,b內容則是http://www.this-is-a-spa.com/b,如果是傳統的導航顯示的話,整個頁面就只有一

個 url http://www.this-is-a-spa.com/

(我相信它的功能應該遠遠不至於此,只是我目前才疏學淺,還沒學到它更深的內容)

******************************************************************************************************************************


在網上查找了一些別人的看法:

1.什麼是前端路由?

  • 路由是根據不同的 url 地址展示不同的內容或頁面

  • 前端路由就是把不同路由對應不同的內容或頁面的任務交給前端來做,之前是通過服務端根據 url 的不同返回不同的頁面實現的。

2.什麼時候使用前端路由?

  • 在單頁面應用(SPA),大部分頁面結構不變,只改變部分內容的使用                                                                                                              (單頁 Web 應用 (single-page application 簡稱爲 SPA) 是一種特殊的 Web 應用。它將所有的活動侷限於一個Web頁面中,僅在該Web頁面初始化時加載相應的HTML、JavaScript 和 CSS。一旦頁面加載完成了,SPA不會因爲用戶的操作而進行頁面的重新加載或跳轉。而是利用 JavaScript 動態的變換HTML的內(採用的是div切換顯示和隱藏),從而實現UI與用戶的交互。由於避免了頁面的重新加載,SPA 可以提供較爲流暢的用戶體驗。)

3.前端路由有什麼優點和缺點?

  • 優點

    • 用戶體驗好,不需要每次都從服務器全部獲取,快速展現給用戶

  • 缺點

    • 使用瀏覽器的前進,後退鍵的時候會重新發送請求,沒有合理地利用緩存

    • 單頁面無法記住之前滾動的位置,無法在前進,後退的時候記住滾動的位置


________________________________________________________________________________________________________________________________

具體的實踐:(代碼爲前面的參考Demo)

首先來個最簡單的,效果就是一個頁面中有2個“導航”,點擊則顯示相應的內容;

下面是關鍵代碼:

index.js

import React from 'react'
import { render } from 'react-dom'
import { Router, Route, hashHistory} from 'react-router'
import App from './modules/App'
import About from './modules/About'
import Repos from './modules/Repos'
import Repo from './modules/Repo'

render((
  <Router history={hashHistory}>
    <Route path="/" component={App}>
      <Route path="/repos" component={Repos}/>
      <Route path="/about" component={About}/>
    </Route>
  </Router>
), document.getElementById('app'))

App.js

import React from 'react'
import NavLink from './NavLink'

export default React.createClass({
  render() {
    return (
      <div>
        <h1>React Router Tutorial</h1>
        <ul role="nav">
          <li><NavLink to="/about">About</NavLink></li>
          <li><NavLink to="/repos">Repos</NavLink></li>
        </ul>
        {this.props.children}
      </div>
    )
  }
})

這裏初學者要注意{this.props.children}這句話,是用來顯示我們路由對應的子組件的;(App裏面包含了Repos和About這2個組件)


當前上面這個還存在一個小問題:如果我頁面一進去想默認先顯示第一個導航怎麼辦?

我們這裏只需要利用IndexRoute這個標籤,寫好我們的默認路由即可:(記得在import中先定義好)

import React from 'react'
import { render } from 'react-dom'
import { Router, Route, hashHistory, IndexRoute} from 'react-router'
import App from './modules/App'
import About from './modules/About'
import Repos from './modules/Repos'
import Repo from './modules/Repo'

render((
  <Router history={hashHistory}>
    <Route path="/" component={App}>
      <IndexRoute path="/repos" component={Repos}/>
      <Route path="/repos" component={Repos}/>
      <Route path="/about" component={About}/>
    </Route>
  </Router>
), document.getElementById('app'))


因爲需求中導航中還有子導航,所以我們的就需要用到路由嵌套;

其實這個的難點在於:如何將我們的需求和路由的結構理清楚,對於初學者來說是一個比較費時的地方。

========================================================================

(我自己列的一個導航路由和組件的關係圖,對比代碼看會清晰不少)

                                                         /repos/reactjs/react-router(Repo組件)

                       /repos(Repos組件){

/(App組件) {                                     /repos/facebook/react(Repo組件)

                      /about(About組件)

========================================================================


先把這個關係列好~每層之間的路由關係其實也就是我們的導航與內容,導航與子導航之間的關係;

   A.最開始頁面進入根路徑/,url就是http://localhost:8080/#/?_k=8a84lu 根路由是App組件

   B.點擊頁面中的About導航後渲染About組件,然後url會變成http://localhost:8080/#/about?_k=rf9brt

   C.點擊Repos導航的時候渲染Repos組件,url變成http://localhost:8080/#/repos?_k=a9umbj

   D.再點擊Repos下面的子導航React Router的時候,渲染Repo組件,url變成http://localhost:8080/#/repos/reactjs/react-router?_k=giihrr....這個就是我們能觀察到的現象


然後就是我們路由的代碼書寫:

<Router history={hashHistory}>
    <Route path="/" component={App}>
      <Route path="/repos" component={Repos}>
        <Route path="/repos/:userName/:repoName" component={Repo}/>
      </Route>
      <Route path="/about" component={About}/>
    </Route>
</Router>
一層層嵌套的關係,可以用這個代碼和我前面列出來的那個關係表對比看一下,就很清楚了。

Repo.js 

import React from 'react'

export default React.createClass({
  render() {
    return (
      <div>
        <h2>{this.props.params.repoName}</h2>
      </div>
    )
  }
})

Repos.js

import React from 'react'
import NavLink from './NavLink'

export default React.createClass({
  render() {
    return (
      <div>
        <h2>Repos</h2>
        <ul>
          <li><NavLink to="/repos/reactjs/react-router">React Router</NavLink></li>
          <li><NavLink to="/repos/facebook/react">React</NavLink></li>
        </ul>
        {this.props.children}
      </div>
    )
  }
})

這裏提一下:

 path="/repos/:userName/:repoName"

這個用到了路由的通配符,其實我們通過觀察,我們可以發現path屬性中的 :userName 和 :repoName就相當於我們的to屬性中的react.js 和react-router,個人認爲就是函數中的形參和實參的關係,我們可以通過this.props.params.xxx來獲取相應的值。


最後我自己總結一下:

     1.路由是可以用來局部刷新頁面的一種方式,主要是通過url的改變來渲染不同的組件,url中定義的路徑就是每個組件的“位置",定義在我們的<Route>標籤中的path屬性中,然後我們通過<Link>標籤的to屬性來找到我們想要的路由,進而來渲染我們想要的組件;

     2.我們是通過{ this.props.childern }來渲染我們的路由所對應的組件 (對於初學者如果遇到路由都對的情況下,還是不能渲染組件的時候,可以看看是不是掉了這句話)

     3.我們可以把<Link>標籤類比我們的<a>標籤,而且它還具有activeClassName屬性,可以定義我們當前導航的樣式class,或者直接把樣式寫在activeStyle裏面也行。

     4.使用<IndexRoute>標籤來定義我們的默認路由,即爲我們的默認”導航“

     5.在進行路由嵌套的時候畫一下關係對比圖,讓自己的大腦更加清晰,書寫代碼的時候會更加流暢

(目前對於路由的研究是淺嘗輒止,繼續學習ing!)





發佈了128 篇原創文章 · 獲贊 54 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章