react-router 學習筆記

来源:http://www.cnblogs.com/miaowwwww/archive/2017/01/23/6343207.html
-Advertisement-
Play Games

前言: 本文為個人學習react-router的總結。包括路由基礎配置,跳轉,許可權管理,組件與路由配置的關係,代碼分割。歡迎交流指導。 一、路由基礎 1.路由配置 & 顯示路由組件的view(類比angular的ui-view) 路由配置:路由匹配的規則 view:放置路由組件的地方(URL匹配了, ...


前言:

  本文為個人學習react-router的總結。包括路由基礎配置,跳轉,許可權管理,組件與路由配置的關係,代碼分割。歡迎交流指導。

一、路由基礎

  1.路由配置 & 顯示路由組件的view(類比angular的ui-view)

  路由配置:路由匹配的規則

render((
    <Router history={ hashHistory }>
        <Route path="/" component={ App }>
            <Route path="select" component={ Select }></Route>
            <Route path="found" component={ Found }></Route>
            <Route path="follow" component={ Follow }></Route>
            <Route path="my" component={ My }>
                <Route path=":myname" component={ MyName }></Route>
                <Route path="mysex" component={ MySex }></Route>
            </Route>
        </Route>
    </Router>
), document.getElementById('root'));

  view:放置路由組件的地方(URL匹配了,然後對應的組件應該放到什麼地方去),

  每一個Route都只是一個組件,子路由就是 this.props.children 裡面的組件,Route通過匹配URL決定顯示哪一個子路由

class App extends PureComponent {
    render() {
        return (
            <div>
                <GlobalNav />
                { this.props.children } { /* this.props.children 是被嵌套在App的組件,相當於放子路由的View*/}
            </div>
        )
    }
}

 

二、預設路由(IndexRoute )

  組件<App /> 的匹配路徑是 ‘/', 有四個子路由,當前路由只是'/',那麼<App />應該顯示什麼頁面呢?

  這裡給與IndexRoute組件 -- 若希望直接使用4個其中一個則使用IndexRedirect

render((
    <Router history={ hashHistory }>
        <Route path="/" component={ App }>
            <IndexRoute component={ IndexApp } />
            <Route path="select" component={ Select }></Route>
            <Route path="found" component={ Found }></Route>
            <Route path="follow" component={ Follow }></Route>
            <Route path="my" component={ My }>
                <Route path=":myname" component={ MyName }></Route>
                <Route path="mysex" component={ MySex }></Route>
            </Route>
        </Route>
    </Router>
), document.getElementById('root'));

 

   如果不使用IndexRoute組件,也還有一種投機取巧的方法,直接在 App組件中,使用  {this.props.children || <IndexApp />} ,在ui展示的層面上修改this.props.children為undefined的情況。

   缺點:這種形式,沒有參與到路由機制中,onEnter,onLeave 等HOOK都無法使用

三、路由跳轉   

  1. IndexLink & Link (active狀態之爭)

   倘若有如下兩個鏈接,正好URL是'/my/mioawwwww', 兩個路由都匹配的了,那麼就是兩個都是active狀態(相應地添加activeStyle,activeClassName的樣式)

<Link to="/my" >Mypage</Link>
<Link to="/my/:myname" >myname</Link>

 

  若你只想為 <Link to="/my/:myname" >myname</Link> 這一個按鈕添加active樣式,就可以為 <Link to="/my" >Mypage</Link> 使用IndexLink

<IndexLink to="/my" >Mypage</IndexLink>
<Link to="/my/:myname" >myname</Link>

  IndexLink是補充Link的,只要URL完整匹配'/my'的時候才會激活active狀態

  2.跳轉參數 to

     2.1:通過 to=’xx/xx' 直接跳轉 <Link to={`/my/${myname}/info`}>check my info</Link> 

     2.2:to=對象,帶參數跳轉(pathname, query, hash, state(額外數據)),註意:這些參數都被存放到this.props.location中

 <li><Link to={{pathname:"/select", hash:'#ahash', query:{foo: 'bar', boo:'boz'}, state:{data:'miao'}  }} activeClassName="GlobalNav-active">精選</Link></li>

     2.3:to=函數,註冊到路由跳轉事件中,每一次路由變化,都會執行該函數,並經最新的location作為參數

<Link to={location => ({ ...location, query: { name: 'ryan' } })}>
  Hello
</Link>

    2.4:不使用Link,在函數內直接操作router

      舊版本:由於router只用的context傳遞路由信息,因此每一個組件都可以輕易的通過this.context.router獲取路由

      新版本:router被放置在this.props中,通過this.props.router可以獲取路由

      註意:push與replace的區別,一個是添加,一個是替換,歷史記錄中被替換的已經不存在了,所以瀏覽器回退不到替換前的頁面。

    changeRouter = () => {
        console.log(this.props)
        // this.props.router.push('/follow');
        // this.props.router.push({
        //     pathname:'/follow',
        //     state:{name:'xxx'},
        //     query: {foo: 'bar'}
        // })
        
        // this.props.router.replace('/follow');
        this.props.router.replace({
            pathname: '/follow',
            query: {foo:'bar'}
        })
    }

 

四、重定向

  <Redirect>:重定向到同等級的其他路由

   <Redirect from="name/xxx" to='mysex' /> 

render((
    <Router history={ browserHistory }>
        <Route path="/" component={ App }>
            <IndexRoute component={ IndexApp } />
            <Route path="select" component={ Select }></Route>
            <Route path="found" component={ Found } onEnter={onEnterHook} onLeave={onLeaveHook}></Route>
            <Route path="follow" component={ Follow }>
            </Route>
            <Route path="my" component={ My } >
                <Redirect from="name/xxx" to='mysex' />
                
                <Route path="name/:myname" component={ MyName }>
                    <Route path="info" component={ MyInfo } ></Route>
                </Route>
                <Route path="mysex" component={ MySex } />
            </Route>
            <Redirect from="*" to='/' />
        </Route>
    </Router>
), document.getElementById('root'));

 

  <IndexRedirect>:從父路由的目錄開始重定向

<Route path="/" component={App}>
  <IndexRedirect to="/welcome" />
  <Route path="welcome" component={Welcome} />
  <Route path="about" component={About} />
</Route>

 

 

五、路由機制的許可權

  1.onEnter

const onEnterHook = (nextState, replace /*,cb*//*若添加cb參數,鉤子變成非同步執行,cb返回之前,將發生阻塞*/) => {
    console.log('onenter', nextState);
    // replace // 是router.replace(),若訪問者沒有許可權,則引導到其他頁面
}

  nextState的屬性

  2.onLeave:與onEnter類似,nextState屬性不同

   3.onChange(prevState, nextState, replace, callback?) ,用於子路由,

    進入該路由的某個子路由是觸發,或者改變query,hash

    一旦添加onChange屬性,則子路由通過onChangeHook決定,Link不起作用

   

 六、組件與路由的一一對應關係,按需載入組件

<Route path="follow" component={ Follow }></Route> // this.props.children;
<Route path="follow" component={ {main:Follow, sidebar: Sidebar} }></Route> // const { main, sidebar } = this.props;

 

   非同步載入組件,使用(需要加上 require.ensure([], (require) => {}) 實現代碼分割

   getComponent(nextState, callback)  &&  getComponents(nextState, callback) 

   cb(err, component) 

  getComponent(nextState, cb) {
    require.ensure([], (require) => {
      cb(null, require('./components/Calendar'))
    })
  }

 

   

 七、每一個Route組件的屬性

 

 

 八、另一種路由配置的方式

const selectRouter = {
    path:'select',
    component: Select
}
const foundRouter = {
    path:'found',
    component: Found
}
const myRouter = {
    path:'my',
    getComponent(nextState,cb) {
        cb(null, My)
    }
}
// import Follow from './components/Follow.js';
const followRouter = {
    path:'follow',
    getComponent(nextState,cb) {
        require.ensure([], (require) => {
            cb(null, require('./components/Follow'))
        })
    }
    // getComponent(nextState, cb) {
    //     cb(null, Follow)
    // }
}
const rootRouter = {
    path: '/',
    component: App,
    // indexRoute: {component:IndexApp},
    childRoutes: [
        selectRouter,
        foundRouter,
        followRouter,
        // require('./components/Follow.index'),
        myRouter
        ]
}
// const rootRouter = {
//     path: '/',
//     component: App,
//     getIndexRoute(partialNextState, cb) {
//         cb(null,  {compoment:IndexApp});
//     },
//     getChildRoutes(location, cb) {
//         cb(null, [
//             selectRouter,
//             foundRouter,
//             followRouter,
//             myRouter
//         ])
//     }
// }
render(
    <Router history={browserHistory} routes={rootRouter} />,
    document.getElementById('root')
)

 

   代碼分割的註意事項:

    1. require.ensure中分割的組件,需要使用module.export 暴露出來

module.exports = xxx; //可獲取xxx組件
export default xxx // 不可獲取xxx組件 

     2. getComponent,getComponents,getIndexRoute,getChildRoutes只是實現了非同步載入,要實現代碼分割還是要使用require.ensure

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 層次選擇器: $("div li")獲取div下的所有li元素(後代、子、子的子......) $("div>li")獲取div下的直接li子元素。 $(".menuitem+div")獲取樣式名為menuitem之後的第一個div元素(不常用)。 $(".menuitem~div")獲取樣式名為m ...
  • yield next和yield* next之間到底有什麼區別?為什麼需要yield* next?經常會有人提出這個問題。雖然我們在代碼中會儘量避免使用yield* next以減少新用戶的疑惑,但還是經常會有人問到這個問題。為了體現自由,我們在koa框架內部使用了yield* next,但是為了避免 ...
  • 2017年也已經開始了快一個月的時間了,然而我卻好像沒有跨進新一年的感覺 過去的一年裡,前端開發這個行業的變化給我的感覺實在是快得有點眼花繚亂應接不暇 各種工程化工具,各種新框架占據了這個行業裡人們日常討論的話題 然而反思回自己的團隊,仍然是停留在比較基礎的開發流程。不得不讓我恍然醒悟,自己真是半年 ...
  • 在JS中,引擎,編譯器,作用域分別扮演以下角色: 引擎:負責整個Js程式的編譯以及執行過程。 編譯器:負責語法分析以及代碼生成等。 作用域:負責收集並維護所有聲明的標示符(變數)組成的一系列查詢,並實施一套嚴格的規則,確定當前執行的代碼對這些標識符的訪問許可權。 下麵用一個小例子來表示: var a ...
  • new document 首頁 列表 內容 聯繫 關於 ...
  • ...
  • Tabslet Yet another jQuery plugin for tabs, lightweight, easy to use and with some extra features Demonstration page Documentation (wiki) 實例DEMO 運行一下 ...
  • 特性說明和原理圖: 標準瀏覽器和Ie9+瀏覽器都支持事件的冒泡和捕獲,而IE8-瀏覽器只支持冒泡 標準和Ie9+瀏覽器用stopPropagation()或cancelBubble阻止事件傳播,而ie8-用e.cancelBubble屬性來阻冒泡,註意ie9不支持cancelBubble屬性(設置後 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...