React.js學(xué)習(xí)筆記(6) router-4全接觸 + ( webpack2以上的實(shí)現(xiàn)按需加載路由 bundle.js )

(一) react-router-dom 安裝

React Router被拆分成下面幾個(gè)包:

  • react-router :React Router 核心
  • react-router-dom 用于 DOM 綁定的 React Router - (用于Web瀏覽器)
  • react-router-redux React Router 和 Redux 的集成 - (搭配redux)
  • react-router-native 用于 React Native 的 React Router -(用于ReactNative)
  • react-router-config 靜態(tài)路由配置的小助手
 npm install react-router-dom --save

(二) 組件

(1) <BrowserRouter>

(1) <BrowserRouter> 簡(jiǎn)介:

對(duì)于網(wǎng)頁項(xiàng)目酪耳,存在<BrowserRouter>與<HashRouter>兩種組件:
<BrowserRouter>組件:在服務(wù)區(qū)來管理動(dòng)態(tài)請(qǐng)求時(shí)使用拉讯。
<HashRouter>組件:用于靜態(tài)網(wǎng)站元镀。

通常爬骤,我們更傾向選擇 <BrowserRouter>

  • BrowserRouter: 瀏覽器自帶的API,restful風(fēng)格(需要后臺(tái)做相應(yīng)的調(diào)整)息尺;
  • HashRouter: 使用hash方式進(jìn)行路由拢肆;
  • MemoryRouter: 在內(nèi)存中管理history辅斟,地址欄不會(huì)變化。在reactNative中使用龟糕。
(2) <BrowserRouter> 屬性:
  • basename: string
    作用:為所有位置添加一個(gè)基準(zhǔn)URL
    使用場(chǎng)景:假如你需要把頁面部署到服務(wù)器的二級(jí)目錄桐磁,你可以使用 basename 設(shè)置到此目錄。

<BrowserRouter basename="/calendar"/>                    // basename:string

<Link to="/today"/> 最終渲染為 renders <a href="/calendar/today">

  • keyLength: number
    作用:設(shè)置它里面路由的 location.key 的長(zhǎng)度讲岁。默認(rèn)是6我擂。(key的作用:點(diǎn)擊同一個(gè)鏈接時(shí)衬以,每次該路由下的 location.key都會(huì)改變,可以通過 key 的變化來刷新頁面扶踊。)
    使用場(chǎng)景:按需設(shè)置泄鹏。

 <BrowserRouter keyLength={12}/>

(2) <Route>

(1) <Route> 組件簡(jiǎn)介:

<Route> 自帶三個(gè) render method 和三個(gè) props 。

  • render methods 分別是:
    <Route component>
    <Route render>
    <Route children>
    每種 render method 都有不同的應(yīng)用場(chǎng)景
    同一個(gè)<Route> 只使用一種 render method 秧耗,大部分情況下你將使用 component 备籽。
    children方式渲染會(huì)不管地址欄是否匹配都渲染一些內(nèi)容,在這里加動(dòng)畫一時(shí)很常見的做法分井。

  • props 分別是:
    match
    location
    history

( match, location, history 使用方法已在文章末尾補(bǔ)充 -2017/11/8 )

三種渲染方式都會(huì)得到三個(gè)屬性match车猬、history、location;
所有的 render method 無一例外都將被傳入這些 props;
渲染組件時(shí)尺锚,route props跟著一起渲染;


<Route path="/user/:username" component={User}/>

const User = ({ match }) => {
  return <h1>Hello {match.params.username}!</h1>
}

  • exact: bool
    如果為 true珠闰,path 為 '/one' 的路由將不能匹配 '/one/two',反之瘫辩,亦然伏嗜。
  • strict: bool
    對(duì)路徑末尾斜杠的匹配。如果為 true伐厌。path 為 '/one/' 將不能匹配 '/one' 但可以匹配 '/one/two'承绸。
  • 如果要確保路由沒有末尾斜杠,那么 strict 和
    exact 都必須同時(shí)為 true
 <Route exact strict path="/one" component={About}/>

(3) <Link>

  • to: 后面可以接字符串挣轨,也可以跟對(duì)象(對(duì)象可以是動(dòng)態(tài)地添加搜索的信息)军熏;

to: string
作用:跳轉(zhuǎn)到指定路徑
使用場(chǎng)景:如果只是單純的跳轉(zhuǎn)就直接用字符串形式的路徑。

to: object
作用:攜帶參數(shù)跳轉(zhuǎn)到指定路徑
作用場(chǎng)景:比如你點(diǎn)擊的這個(gè)鏈接將要跳轉(zhuǎn)的頁面需要展示此鏈接對(duì)應(yīng)的內(nèi)容卷扮,又比如這是個(gè)支付跳轉(zhuǎn)荡澎,需要把商品的價(jià)格等信息傳遞過去。


<Link to={{
  pathname: '/courses',
  search: '?sort=name',
  hash: '#the-hash',
  state: { fromDashboard: true }
}}/>

  • replace: bool

replace: 當(dāng)設(shè)置為true時(shí)晤锹,點(diǎn)擊鏈接后將使用新地址替換掉訪問歷史記錄里面的原地址摩幔。

為 true 時(shí),點(diǎn)擊鏈接后將使用新地址替換掉上一次訪問的地址鞭铆,什么意思呢或衡,比如:你依次訪問 '/one' '/two' '/three' ’/four' 這四個(gè)地址,如果回退衔彻,將依次回退至 '/three' '/two' '/one' 薇宠,這符合我們的預(yù)期,假如我們把鏈接 '/three' 中的 replace 設(shè)為 true 時(shí)艰额。依次點(diǎn)擊 one two three four 然后再回退會(huì)發(fā)生什么呢澄港?會(huì)依次退至 '/three' '/one'!

(4) <NavLink>

<NavLink>是<Link>的一個(gè)特定版本, 會(huì)在匹配上當(dāng)前URL的時(shí)候會(huì)給已經(jīng)渲染的元素添加樣式參數(shù)柄沮;

  • activeClassName: string
    導(dǎo)航選中激活時(shí)候應(yīng)用的樣式名回梧,默認(rèn)樣式名為 active
  • activeStyle: object
    如果不想使用樣式名就直接寫style
  • isActive废岂,添加額外邏輯判斷是否生效 (決定導(dǎo)航是否激活,或者在導(dǎo)航激活時(shí)候做點(diǎn)別的事情狱意。不管怎樣湖苞,它不能決定對(duì)應(yīng)頁面是否可以渲染。)

<NavLink
  to="/faq"
  activeClassName="selected"
>FAQs</NavLink>

(5) <Switch>

  • <Switch>會(huì)遍歷自身的子元素(即路由)并對(duì)第一個(gè)匹配當(dāng)前路徑的元素進(jìn)行渲染详囤。
    ( 只渲染出第一個(gè)與當(dāng)前訪問地址匹配的 <Route> 或 <Redirect> )
  • <Switch> 對(duì)于轉(zhuǎn)場(chǎng)動(dòng)畫也非常適用财骨,因?yàn)楸讳秩镜穆酚珊颓耙粋€(gè)被渲染的路由處于同一個(gè)節(jié)點(diǎn)位置!

<Fade>
  <Switch>
    {/* 用了Switch 這里每次只匹配一個(gè)路由藏姐,所有只有一個(gè)節(jié)點(diǎn)隆箩。 */}
    <Route/>
    <Route/>
  </Switch>
</Fade>



<Fade>
  <Route/>
  <Route/>
  {/* 不用 Switch 這里可能就會(huì)匹配多個(gè)路由了,即便匹配不到羔杨,也會(huì)返回一個(gè)null捌臊,使動(dòng)畫計(jì)算增加了一些麻煩。 */}
</Fade>

(6) <Redirect>

  • <Redirect/>可以寫在<Route/>的render屬性里面兜材,也可以跟<Route/>平級(jí)理澎;
  • to: string
    重定向的 URL 字符串
  • to: object
    重定向的 location 對(duì)象
  • push: bool
    若為真,重定向操作將會(huì)把新地址加入到訪問歷史記錄里面曙寡,并且無法回退到前面的頁面糠爬。
  • from: string
    需要匹配的將要被重定向路徑。

<Switch>
  <Route exact path="/" component={Home}/>

  <Route path="/users" component={Users}/>
  <Redirect from="/accounts" to="/users"/>                     // 將/accounts重定向到/users

  <Route component={NoMatch}/>
</Switch>



------------------------------------------------------------------

2018-1-23更

import React, { Component } from 'react';
import {Route, Redirect} from 'react-router-dom';                 // 引入Redirect
import A from '../component/a.js';
import B from '../component/b.js';

class RouterOne extends Component {
  render() {
    return (
      <div className="R">
        <Route  path="/a" component={ A }/>
        <Route  path="/b" render={() => <Redirect to="/a"/>}/>    // 使用Redirect
      </div>
    );
  }
}

export default RouterOne;

(7) <Prompt> 提示

當(dāng)用戶離開當(dāng)前頁面前做出一些提示卵皂。用在Link或者Route的地方都行

  • message: string
    當(dāng)用戶離開當(dāng)前頁面時(shí)秩铆,設(shè)置的提示信息砚亭。
  • message: func
    當(dāng)用戶離開當(dāng)前頁面時(shí)灯变,設(shè)置的回掉函數(shù),函數(shù)是有默認(rèn)參數(shù)的捅膘。
  • when: bool
    通過設(shè)置一定條件要決定是否啟用 Prompt添祸,屬性值為true時(shí)啟用防止轉(zhuǎn)換;

<Prompt message="確定要離開寻仗?" />






(8) React-router4 使用


  import {
    BrowserRouter as Router, // 或者是HashRouter刃泌、MemoryRouter
    Route,   // 這是基本的路由塊
    Link,    // 這是a標(biāo)簽
    Switch   // 這是監(jiān)聽空路由的
    Redirect // 這是重定向
    Prompt   // 防止轉(zhuǎn)換  
  } from 'react-router-dom'

實(shí)例:

index.js入口文件


import React from 'react';
import ReactDOM from 'react-dom';
import RouterComp from './router/router.js';

import {
  BrowserRouter
} from 'react-router-dom';

import CommentApp from './commentApp'; 

import './index.css'

ReactDOM.render(
  (
    <BrowserRouter>
      <CommentApp>                                 
        <RouterComp />                                // RouterComp 存放所有Route
      </CommentApp>    
    </BrowserRouter>
  ),document.getElementById('root'))




------------------------------------------------------------------------------------------
router.js



import React, {Component} from 'react';
import {
    Route, Redirect, Switch, Prompt
} from 'react-router-dom';
import CommentApp from '../commentApp';
import ArrayC from '../component/ArrayC/ArrayC';
import ObjectC from '../component/ObjectC/ObjectC';
import RedirectComponents from '../component/Redirect/redirect';

export default class RouterA extends Component {
    render() {
        return(
            <div>
                <Switch>                                              // 匹配第一個(gè)匹配到的Route
                    <Route path="/array" component={ArrayC}/>

                    <Route path="/object" component={ObjectC}/>
                    <Redirect  from="/redirectgo" to="/object"/>               // 路由重定向

                    <Route path="/redirectgo" component={RedirectComponents}/>
                </Switch>
                <Prompt message="確定要離開?" />                               // 跳轉(zhuǎn)前提示
            </div>
        )
    }
}




------------------------------------------------------------------------------------------

commentApp.js



import React, {Component} from 'react'
import {Link, NavLink} from 'react-router-dom'


class CommentApp extends Component {

    render() {
        return (
            <div className='wrapper'>

                <NavLink to="/array" activeClassName="abc" className='context2'>
                    <div>
                        數(shù)組測(cè)試
                    </div>
                </NavLink>
                <Link to="/object">
                    <div className='context3'>
                        對(duì)象測(cè)試
                    </div>
                </Link>
                <Link to="/redirectgo">
                    <div className='context4'>
                        重定向測(cè)試
                    </div>
                </Link>

                <div className="ArrayC">
                    {this.props.children}           // <RouterComp /> 組件加載的位置               
                </div>

             </div>
        )
    }
}

export default CommentApp







(九) location

location 是指你當(dāng)前的位置署尤,將要去的位置耙替,或是之前所在的位置

它看起來像這樣:

{
  key: 'ac3df4', // not with HashHistory!
  pathname: '/somewhere'
  search: '?some=search-string',
  hash: '#howdy',
  state: {
    [userDefined]: true
  }
}

(1)路由器將在幾個(gè)地方為您提供一個(gè) location 對(duì)象:

  • 在 Route component 中,以 this.props.location 獲取
  • 在 Route render 中曹体,以 ({location}) => () 方式獲取
  • 在 Route children 中俗扇,以 ({location}) => () 方式獲取
  • 在 withRouter 中,以 this.props.location 的方式獲取

(2) location 對(duì)象不會(huì)發(fā)生改變箕别,因此可以在生命周期的回調(diào)函數(shù)中使用 location 對(duì)象來查看當(dāng)前頁面的訪問地址是否發(fā)生改變铜幽。這種技巧在獲取遠(yuǎn)程數(shù)據(jù)以及使用動(dòng)畫時(shí)非常有用



componentWillReceiveProps(nextProps) {
  if (nextProps.location !== this.props.location) {
    // navigated!
  }
}

(3) 您可以使用location代替字符串導(dǎo)航到各個(gè)位置:

  • <Link to={location} />
  • <NaviveLink to={location} />
  • <Redirect to={location />
  • history.push(location)
  • history.replace(location)
location
它看起來像這樣:


{
  key: 'ac3df4', // not with HashHistory!
  pathname: '/somewhere'
  search: '?some=search-string',
  hash: '#howdy',
  state: {
    [userDefined]: true
  }
}

(十) match

(1)match 對(duì)象包含了 <Route path> 如何與 URL 匹配的信息滞谢,具有以下屬性:

  • params : object 路徑參數(shù),通過解析 URL 中的動(dòng)態(tài)部分獲得鍵值對(duì)
  • isExact : bool 為 true 時(shí)除抛,整個(gè) URL 都需要匹配
  • path : string 用來匹配的路徑模式狮杨,用于創(chuàng)建嵌套的 <Route>
  • url : string URL 匹配的部分,用于嵌套的 <Link>

(2) 在以下情境中可以獲取 match 對(duì)象 ( 和location獲取方法一樣 )

  • 在 Route component 中到忽,以 this.props.match獲取
  • 在 Route render 中橄教,以 ({match}) => () 方式獲取
  • 在 Route children 中,以 ({match}) => () 方式獲取
  • 在 withRouter 中喘漏,以 this.props.match的方式獲取
  • matchPath 的返回值

當(dāng)一個(gè) Route 沒有 path 時(shí)颤陶,它會(huì)匹配一切路徑。

(十一) history

在組件中使用this.props.history
包含了以下信息:

  • length 保存的路由記錄條數(shù)
  • action:push陷遮,pop滓走,replace
  • location :當(dāng)前路由信息
  • goBack
  • goForward等
history包含內(nèi)容










2017/11/12日更新

(十二) react-router4 實(shí)現(xiàn)按需加載

  • (1) 首先使用官方提供的 bundle 組件 (這個(gè)組件和你用webpack打包的bundle沒啥關(guān)系)
    Bundle.js的主要功能就是接收一個(gè)組件異步加載的方法,并返回相應(yīng)的react組件

  • 這里要注意:
    由于webpack2以上已經(jīng)不支持import loader 了帽馋,所以下面的方法不用 bundle-loader插件

bundle.js



由于import是promise結(jié)構(gòu)搅方,所有在下面的load = XXXXXX部分也要用promise結(jié)構(gòu)


import React, {Component} from 'react'

export default class Bundle extends Component {

  constructor(props) {
        super(props);
        this.state = {
            mod: null
        };
    }

    componentWillMount() {
        this.load(this.props)
    }
    componentWillReceiveProps(nextProps) {
        if (nextProps.load !== this.props.load) {
            this.load(nextProps)
        }
    }



/*
    load = (props) => {
        this.setState({
            mod:null
        })
        props.load((mod) => {
            this.setState({
                mod:mod.default?mod.default:mod
            })
        })
    }
*/

上面注釋這段需要修改為:
load(props) {
        this.setState({
            mod: null
        });
        //注意這里,使用Promise對(duì)象; mod.default導(dǎo)出默認(rèn)
        props.load().then((mod) => {
            this.setState({
                mod: mod.default ? mod.default : mod
            });
        });
    }




 render() {
        return this.state.mod ? this.props.children(this.state.mod) : null;
    }


}


  • (2)
    1.在router.js中引入官方提供的bundle.js組件
    2.在Route組件的component中使用bundle.js
    3.在<Bundle load={ () => import('........') }中采用import方法

import React, {Component} from 'react';
// import { Route, Redirect, Switch, Prompt } from 'react-router-dom';
import { Route,  Switch } from 'react-router-dom';

import Bundle from '../bundle/bundle.js';



export default class RouterA extends Component {
    render() {
        return(
            <div>
                <Switch>

                    <Route 
                    path="/array/go?name=123" 
                    component={ () => <Bundle load={() => import('../component/ArrayC/ArrayC')}>{ C => <C />}</Bundle>} 
                    />

                    <Route 
                    path="/object" 
                    component={ () => <Bundle load={ () => import('../component/ObjectC/ObjectC')}>{ C => <C /> }</Bundle>}
                    />

                    <Route
                     path="/redirectgo" 
                     component={ () => <Bundle load={ () => import('../component/Redirect/redirect')}>{ C => <C /> }</Bundle>} 
                     />
                     
                    <Route 
                    path="/string" 
                    component={ () => <Bundle load={ () => import('../component/string/strig.js')}>{ C => <C /> }</Bundle>}
                    />  
                                   
                </Switch>
            </div>
        )
    }
}

按需加載效果圖

( 填坑 ) http://www.reibang.com/p/547aa7b92d8c
( 踩坑 ) http://www.reibang.com/p/d712a5030c13

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绽族,一起剝皮案震驚了整個(gè)濱河市姨涡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吧慢,老刑警劉巖涛漂,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異检诗,居然都是意外死亡匈仗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門逢慌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悠轩,“玉大人,你說我怎么就攤上這事攻泼』鸺埽” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵忙菠,是天一觀的道長(zhǎng)何鸡。 經(jīng)常有香客問我,道長(zhǎng)牛欢,這世上最難降的妖魔是什么骡男? 我笑而不...
    開封第一講書人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮氢惋,結(jié)果婚禮上洞翩,老公的妹妹穿的比我還像新娘稽犁。我一直安慰自己,他們只是感情好骚亿,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開白布已亥。 她就那樣靜靜地躺著,像睡著了一般来屠。 火紅的嫁衣襯著肌膚如雪虑椎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評(píng)論 1 310
  • 那天俱笛,我揣著相機(jī)與錄音捆姜,去河邊找鬼。 笑死迎膜,一個(gè)胖子當(dāng)著我的面吹牛泥技,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播磕仅,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼珊豹,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了榕订?” 一聲冷哼從身側(cè)響起店茶,我...
    開封第一講書人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎劫恒,沒想到半個(gè)月后贩幻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡两嘴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年丛楚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溶诞。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸯檬,死狀恐怖决侈,靈堂內(nèi)的尸體忽然破棺而出螺垢,到底是詐尸還是另有隱情,我是刑警寧澤赖歌,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布枉圃,位于F島的核電站,受9級(jí)特大地震影響庐冯,放射性物質(zhì)發(fā)生泄漏孽亲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一展父、第九天 我趴在偏房一處隱蔽的房頂上張望返劲。 院中可真熱鬧玲昧,春花似錦、人聲如沸篮绿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽亲配。三九已至尘应,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吼虎,已是汗流浹背犬钢。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留思灰,地道東北人玷犹。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像洒疚,于是被迫代替她去往敵國(guó)和親箱舞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容