天天看點

【React】路由

0、單頁應用程式

  • SPA:​

    ​Single Page Application​

    ​ 單頁面應用程式,整個應用中隻有一個頁面(index.html)
  • MPA :​

    ​Multiple Page Application​

    ​多頁面應用程式,整個應用中有很多個頁面(*.html)

​​SPA ​​​​網易雲音樂​​

優勢

  1. 加快頁面響應速度,降低了對伺服器的壓力
  • 傳統的多頁面應用程式,每次請求伺服器傳回的都是一整個完整的頁面
  • 單頁面應用程式隻有第一次會加載完整的頁面,以後每次請求僅僅擷取必要的資料
  1. 更好的使用者體驗,運作更加流暢

缺點

不利于 SEO 搜尋引擎優化

  • 因為 爬蟲 隻爬取 HTML 頁面中的文本内容,不會執行 JS 代碼
  • 可以通過 SSR(服務端渲染 Server Side Rendering)來解決 SEO 問題
  • 解釋:先在伺服器端把内容渲染出來,然後,傳回給浏覽器的就是純 HTML 内容了
  • 頁面靜态化,比如,對于一個電商應用可以為每一個商品生産一個靜态的HTML頁面,靜态 HTML 頁面中是帶有文字内容的,是以,有利于 SEO 的

1、React 路由

1.1 React 路由介紹

現代的前端應用大多都是 SPA(單頁應用程式),也就是隻有一個 HTML 頁面的應用程式。因為它的使用者體驗更好、對伺服器的壓力更小,是以更受歡迎。為了有效的使用單個頁面來管理原來多頁面的功能,前端路由應運而生。前端路由的功能:讓使用者從一個視圖(頁面)導航到另一個視圖(頁面)

  • 前端路由是一套映射規則,在React中,是URL路徑與元件的對應關系
  • 使用 React 路由簡單來說就是:配置路徑群組件(配對)

1.2 模拟路由的實作

import React, { PureComponent } from 'react'
import ReactDOM from 'react-dom'
import Home from './pages/Home'
import My from './pages/My'
import Friend from './pages/Friend'
class App extends PureComponent {
  state = {
    currentHash: '',
  }
  // hashchange: 錨點值(hash)改變就會觸發
  componentDidMount() {
    // 注冊事件
    window.addEventListener('hashchange', () => {
      console.log('hash值變了', window.location.hash)
      this.setState({
        currentHash: window.location.hash.slice(1),
      })
    })
  }
  render() {
    const { currentHash } = this.state
    return (
      <div>
        <h1>app元件</h1>
        <ul>
          <li>
            <a href="#/home">首頁</a>
          </li>
          <li>
            <a href="#/my">我的音樂</a>
          </li>
          <li>
            <a href="#/friend">我的朋友</a>
          </li>
        </ul>
        {currentHash === '/home' && <Home></Home>}
        {currentHash === '/my' && <My></My>}
        {currentHash === '/friend' && <Friend></Friend>}
      </div>
    )
  }
}

// 渲染元件
ReactDOM.render(<App />, document.getElementById('root'))      

2、路由基本使用

2.1 基本步驟

  • 安裝
yarn add react-router-dom      
  • ​react-router-dom​

    ​這個包提供了三個核心的元件
import { HashRouter, Route, Link } from 'react-router-dom'      
  • 使用​

    ​HashRouter​

    ​包裹整個應用,一個項目中隻會有一個Router
<Router>
    <div className="App">
    // … 省略頁面内容
    </div>
</Router>      
  • 使用Link指定導航連結
<Link to="/first">頁面一</Link>
<Link to="/two">頁面二</Link>      
  • 使用​

    ​Route​

    ​指定路由規則
// 在哪裡寫的Route,最終比對到的元件就會渲染到這
<Route path="/first" component={First}></Route>      

2.2 Router詳細說明

  • Router 元件:包裹整個應用,一個 React 應用隻需要使用一次
  • 兩種常用 Router:​

    ​HashRouter​

    ​​ 和​

    ​BrowserRouter​

  • HashRouter:使用 URL 的哈希值實作(​

    ​localhost:3000/#/first​

    ​)
  • BrowserRouter:使用 H5 的 history API 實作(​

    ​localhost:3000/first​

    ​)

最佳實踐

import { HashRouter as Router, Route, Link } from 'react-router-dom'      

2.3 路由的執行過程

  1. 點選 Link 元件(a标簽),修改了浏覽器位址欄中的 url
  2. React 路由監聽到位址欄 url 的變化 hashChange popState
  3. React 路由内部周遊所有 Route 元件,使用路由規則(path)與 pathname(hash)進行比對
  4. 當路由規則(path)能夠比對位址欄中的 pathname(hash) 時,就展示該 Route 元件的内容

2.4 Link與NavLink

  • to屬性,将來會渲染成a标簽的href屬性
  • ​Link​

    ​元件無法實作導航的高亮效果
  • to屬性,用于指定位址,會渲染成a标簽的href屬性
  • activeClass: 用于指定高亮的類名,預設​

    ​active​

  • exact: 精确比對,表示必須精确比對類名才生效

2.5 Route

  • path 的說明
  • 預設情況下,/能夠比對任意/開始的路徑
  • 如果 path 的路徑比對上了,那麼就可以對應的元件就會被 render
  • 如果 path 沒有比對上,那麼會 render null
  • 如果沒有指定 path,那麼一定會被渲染
  • exact 的說明, exact 表示精确比對某個路徑
  • 一般來說,如果路徑配置了 /, 都需要配置 exact 屬性

2.6 Switch與404

  • 通常,我們會把​

    ​Route​

    ​​包裹在一個​

    ​Switch​

    ​元件中
  • 在​

    ​Switch​

    ​元件中,不管有多少個路由規則比對到了,都隻會渲染第一個比對的元件
  • 通過​

    ​Switch​

    ​元件非常容易的就能實作404錯誤頁面的提示
<Switch>
  <Route exact path="/" component={Home}/>
  <Route path="/about" component={About}/>
  <Route path="/user" component={User}/>
  <Route component={NoMatch}/>
</Switch>      

3、嵌套路由的配置

  • 在React中,配置嵌套路由非常的簡單,因為​

    ​Route​

    ​就是一個元件,可以在任意想配置的地方進行配置
  • 但是配置嵌套路由的時候,需要對路徑進行處理,必須要先比對到父級路由,才能比對到子路由
// 通過/home可以比對Home父元件  再通過/list比對子元件
<Route path="/home/list" component={List} />      

4、程式設計式導航

  • 場景:點選登入按鈕,登入成功後,通過代碼跳轉到背景首頁,如何實作?
  • 程式設計式導航:通過 JS 代碼來實作頁面跳轉
  • history 是 React 路由提供的,用于擷取浏覽器曆史記錄的相關資訊
  • push(path):跳轉到某個頁面,參數 path 表示要跳轉的路徑
  • go(n): 前進或後退到某個頁面,參數 n 表示前進或後退頁面數量(比如:-1 表示後退到上一頁)
class Login extends Component {
    handleLogin = () => {
        // ...
        this.props.history.push('/home')
    }
    render() {...省略其他代碼}
}      

5、動态路由與路由參數擷取

  • 可以使用​

    ​:id​

    ​的方式來配置動态的路由參數
// 可以比對 /users/1  /users/2  /users/xxx
<Route path="/users/:id" component={Users} />      
  • 在元件中,通過​

    ​props​

    ​可以接收到路由的參數
render(){
    console.log(this.props.match.params)
}