筆記:React-router、react-router-dom、connected-react-router 學習


2020-04-15:

筆記:React-router、react-router-dom、connected-react-router 學習

 

https://react-guide.github.io/react-router-cn/docs/guides/basics/RouteMatching.html

https://reacttraining.com/react-router/web/api/Switch

 

本篇是基於一個疑問開始的:

a標簽和connected-react-router中push方法都分別通過什么方式改變路由?

從結果直接說明:

1、如果使用了connected-react-router把react-router綁定到redux上,a標簽才會跟redux出現關系,同時也才能使用上push;

2、a標簽通過主動的方式進行跳轉,react-router監聽到這個行為后一方面進行路由跳轉一方面通過connected-react-router發起一個action更新redux state

3、push是從redux出發,拋出一個action,再進行跳轉。

 


 

一、路由配置:

  更應該使用絕對路徑的理由

    1、在多層嵌套路由中使用絕對路徑的能力讓我們對 URL 擁有絕對的掌控。我們無需在 URL 中添加更多的層級,從而可以使用更簡潔的 URL。

    2、如果一個路由使用了相對路徑,那么完整的路徑將由它的所有祖先節點的路徑和自身指定的相對路徑拼接而成。使用絕對路徑可以使路由匹配行為忽略嵌套關系。

  渲染四個URL:

import React from 'react'
import { Router, Route, Link } from 'react-router'

const App = React.createClass({
  render() {
    return (
      <div>
        <h1>App</h1>
        <ul>
          <li><Link to="/about">About</Link></li>    // 用Link組件替代a標簽
          <li><Link to="/inbox">Inbox</Link></li>
        </ul>
        {this.props.children}
      </div>
    )
  }
})

const About = React.createClass({
  render() {
    return <h3>About</h3>
  }
})

const Inbox = React.createClass({
  render() {
    return (
      <div>
        <h2>Inbox</h2>
        {this.props.children || "Welcome to your Inbox"}
      </div>
    )
  }
})

const Message = React.createClass({
  render() {
    return <h3>Message {this.props.params.id}</h3>
  }
})

React.render(( <Router>
    <Route path="/" component={App}>
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        <Route path="/messages/:id" component={Message} />

        {/* 跳轉 /inbox/messages/:id 到 /messages/:id */}
        <Redirect from="messages/:id" to="/messages/:id" />     // 利用重定向兼容新舊url
      </Route>
    </Route>
  </Router>
), document.body)

 

二、進入和離開的Hook:

  Route 可以定義 onEnter 和 onLeave 兩個 hook ,這些hook會在頁面跳轉確認時觸發一次。這些 hook 對於一些情況非常的有用,例如權限驗證或者在路由跳轉前將一些數據持久化保存起來

 

三、路由匹配原理:

  路由擁有三個屬性來決定是否“匹配“一個 URL:

  1. 嵌套關系:當一個給定的 URL 被調用時,整個集合中(命中的部分)都會被渲染。嵌套路由被描述成一種樹形結構。React Router 會深度優先遍歷整個路由配置來尋找一個與給定的 URL 相匹配的路由。
  2. 路徑語法:路由路徑是匹配一個(或一部分)URL 的 一個字符串模式
    1. 幾個特殊的符號:

      • :paramName – 匹配一段位於 /? 或 # 之后的 URL。 命中的部分將被作為一個參數
      • () – 在它內部的內容被認為是可選的
      • * – 匹配任意字符(非貪婪的)直到命中下一個字符或者整個 URL 的末尾,並創建一個 splat 參數
        <Route path="/hello/:name">         // 匹配 /hello/michael 和 /hello/ryan
        <Route path="/hello(/:name)">       // 匹配 /hello, /hello/michael 和 /hello/ryan
        <Route path="/files/*.*">           // 匹配 /files/hello.jpg 和 /files/path/to/hello.jpg

         

  3. 優先級:路由算法會根據定義的順序自頂向下匹配路由。因此,當你擁有兩個兄弟路由節點配置時,你必須確認前一個路由不會匹配后一個路由中的路徑。例如,千萬不要這么做:
// not do this

<Route path="/comments" ... />
<Redirect from="/comments" ... />

 

 

四、History:

  React Router 是建立在 history 之上的。 簡而言之,一個 history 知道如何去監聽瀏覽器地址欄的變化, 並解析這個 URL 轉化為 location 對象, 然后 router 使用它匹配到路由,最后正確地渲染對應的組件。

 

history.js: 一個無刷新就可改變瀏覽器欄地址的插件:

  提供了window.history一系列api,目的是幫助構建單頁面無刷新網站。地址修改了,而頁面只有局部dom被修改,這樣能省去每次都重新渲染降低性能損耗,而且能看到動態效果。

  

react-router中history的常見形式:

  1、browserHistory(更好兼容瀏覽器): React Router 的應用推薦的 history。它使用瀏覽器中的 History API 用於處理 URL,創建一個像example.com/some/path這樣真實的 URL 。

    對舊版瀏覽器的兼容 :如果我們能使用瀏覽器自帶的 window.history API,那么我們的特性就可以被瀏覽器所檢測到。如果不能,那么任何調用跳轉的應用就會導致 全頁面刷新。

    它不需要被實例化,直接 import { browserHistory } from 'react-router',< Router history={browserHistory}>

  2、createHashHistory(方便調試) :  使用 URL 中的 hash(#)部分去創建形如 example.com/#/some/path 的路由。

 

五、默認路由與IndexLink:

  這是關於默認路由(首頁)的配置:

  1、假如這個路由Home想使用如 onEnter hook這些路由機制時,由於其沒有渲染的位置,而無法使用,此時,需要用到IndexRoute渲染Home:

<Router>
  <Route path="/" component={App}>
    <IndexRoute component={Home}/>
    <Route path="accounts" component={Accounts}/>
    <Route path="statements" component={Statements}/>
  </Route>
</Router>

 

  2、如果你在這個 app 中使用 <Link to="/">Home</Link> , 它會一直處於激活狀態,因為所有的 URL 的開頭都是 / 。 這確實是個問題,因為我們僅僅希望在 Home 被渲染后,激活並鏈接到它。

如果需要在 Home 路由被渲染后才激活的指向 / 的鏈接,請使用 <IndexLink to="/">Home</IndexLink>

 

(基礎部分到此,高級部分可能后補)

 


 

React-router-dom:

  基於react-router(z),加入了在瀏覽器運行環境下的一些功能,如Switch

1、<Switch>:

  <Route> 的機制是只要匹配到的view都全部重新渲染,這樣浪費性能,<Switch>做到只渲染匹配到的第一個路由的頁面。


let routes = (
  <Switch>
    <Route exact path="/">
      <Home />
    </Route>
    <Route path="/about">
      <About />
    </Route>
    <Route path="/:user">
      <User />
    </Route>
    <Route>
      <NoMatch />
    </Route>
  </Switch>
);

 


 

connected-react-router:

  是一個綁定react-router到redux的組件,來實現雙向綁定router的數據到redux store中,這么做的好處就是讓應用更Redux化,可以在action中實現對路由的操作

// app.ts


import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {Store} from 'redux';
import {Provider} from 'react-redux';
import {Persistor} from 'redux-persist';
import {PersistGate} from 'redux-persist/integration/react';
import {ConnectedRouter} from 'connected-react-router';
import {History} from 'history';


export const render = (
    store : Store, history : History, persistor : Persistor,
) => ReactDOM.render((
    <Provider store={store}>
        <ConnectedRouter history={history}>
            <PersistGate loading={null} persistor={persistor}>
                <App />
            </PersistGate>
        </ConnectedRouter>
    </Provider>
), document.getElementById('root'));


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

// index.ts



import {createHashHistory} from 'history';
import * as moment from 'moment';
import 'moment/locale/zh-cn';

import createStore from '@main/model';
import {render} from './app';
import './index.module.less';


moment.locale('zh_cn');

export const history = createHashHistory();
const {store, persistor} = createStore(history);
store.dispatch({type : 'INITIALIZE'});

render(store, history, persistor);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM