<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          (重磅來襲)react-router-dom 簡明教程

          共 10986字,需瀏覽 22分鐘

           ·

          2021-02-22 00:25

          react-router-dom 簡明教程

          我們需要?jiǎng)?chuàng)建 react-pro 項(xiàng)目

          create-react-app?react-pro

          cd?react-pro

          yarn?add?react-router-dom

          我們看到的目錄如下:

          在 src 下新建一個(gè) HelloRouter.js,代碼如下:

          import?React,?{?PureComponent?}?from?'react';
          import?{
          ????BrowserRouter?as?Router,
          ????Switch,
          ????Route,
          ????Link
          }?from?"react-router-dom";

          //?將路由拆分成數(shù)組的形式,有點(diǎn)像?vue?路由配置
          const?routes?=?[
          ????{
          ????????to:?'/',
          ????????content:?'Home'
          ????},
          ????{
          ????????to:?'/about',
          ????????content:?'About'
          ????},
          ????{
          ????????to:?'/users',
          ????????content:?'Users'
          ????}
          ]

          //?創(chuàng)建組件的一種形式,變量的形式
          const?lis?=?routes.map((item,?index)?=>?{
          ????return?(
          ????????<li?key={index}>
          ????????????<Link?to={item.to}>
          ????????????????{item.content}
          ????????????Link>

          ????????li>
          ????)
          })

          //?類組件的形式
          class?Home?extends?PureComponent?{
          ????render()?{
          ????????return?<h2>Homeh2>;
          ????}
          }

          class?About?extends?PureComponent?{
          ????render()?{
          ????????return?<h2>Abouth2>;
          ????}
          }

          class?Users?extends?PureComponent?{
          ????render()?{
          ????????return?<h2>Usersh2>;
          ????}
          }


          //?這里的?Switch?Route?有點(diǎn)類似?js?中的?switch?case?表示精準(zhǔn)匹配
          export?default?class?HelloRouter?extends?PureComponent?{
          ????render()?{
          ????????return?(
          ????????????
          ????????????????

          ????????????????????

          ????????????????????{/*?A??looks?through?its?children?s?and
          ????????????????renders?the?first?one?that?matches?the?current?URL.?*/}
          ????????????????????
          ????????????????????????
          ????????????????????????
          ????????????????????????
          ????????????????????

          ????????????????

          ????????????

          ????????);
          ????}
          }

          效果如下:

          嵌套路由

          接下來我們就來寫寫 react 的嵌套路由;

          首先我們?cè)?src 下新建一個(gè) QianTaoRouter.js,具體代碼如下:

          import?React,?{?PureComponent?}?from?'react';
          import?{
          ????BrowserRouter?as?Router,
          ????Switch,
          ????Route,
          ????Link,
          ????useParams,
          ????useRouteMatch
          }?from?"react-router-dom";

          const?routes?=?[
          ????{
          ????????to:?'/',
          ????????content:?'Home'
          ????},
          ????{
          ????????to:?'/about',
          ????????content:?'About'
          ????},
          ????{
          ????????to:?'/users',
          ????????content:?'Users'
          ????},
          ????{
          ????????to:?'/topics',
          ????????content:?'Topics'
          ????}
          ]

          const?lis?=?routes.map((item,?index)?=>?{
          ????return?(
          ????????<li?key={index}>
          ????????????<Link?to={item.to}>
          ????????????????{item.content}
          ????????????Link>

          ????????li>
          ????)
          })


          class?Home?extends?PureComponent?{
          ????render()?{
          ????????return?<h2>Homeh2>;
          ????}
          }

          class?About?extends?PureComponent?{
          ????render()?{
          ????????return?<h2>Abouth2>;
          ????}
          }

          class?Users?extends?PureComponent?{
          ????render()?{
          ????????return?<h2>Usersh2>;
          ????}
          }

          function?Topic()?{
          ????let?{?topicId?}?=?useParams();
          ????return?<h3>Requested?topic?ID:?{topicId}h3>;
          }

          function?Topics()?{
          ????let?match?=?useRouteMatch();
          ????console.log("matach",?match)
          ????return?(
          ????????

          ??????????

          Topics


          ????
          ??????????

            ????????????

          • ??????????????Components
            ????????????

          • ????????????

          • ??????????????
            ????????????????Props?v.?State
            ??????????????
            ????????????

          • ??????????

          ????
          ??????????{/*?The?Topics?page?has?its?own??with?more?routes
          ??????????????that?build?on?the?/topics?URL?path.?You?can?think?of?the
          ??????????????2nd??here?as?an?"index"?page?for?all?topics,?or
          ??????????????the?page?that?is?shown?when?no?topic?is?selected?*/}
          ??????????
          ????????????
          ??????????????
          ????????????

          ????????????
          ??????????????

          Please?select?a?topic.


          ????????????
          ??????????

          ????????

          ??????);
          }



          export?default?class?HelloRouter?extends?PureComponent?{
          ????render()?{
          ????????return?(
          ????????????
          ????????????????

          ????????????????????

          ????????????????????{/*?A??looks?through?its?children?s?and
          ????????????????renders?the?first?one?that?matches?the?current?URL.?*/}
          ????????????????????
          ????????????????????????
          ????????????????????????
          ????????????????????????
          ????????????????????????
          ????????????????????

          ????????????????

          ????????????

          ????????);
          ????}
          }

          其中引人注意的是

          • useRouteMatch 用于解析路由對(duì)象
          • useParams 用于解析路由參數(shù)

          主要組件

          路由組件: BrowserRouter和HashRouter

          BrowserRouter使用瀏覽器的History API來管理url及與瀏覽器進(jìn)行交互, 需要服務(wù)器增加配置以讓所有的url請(qǐng)求返回同一個(gè)頁面

          HashRouter將頁面當(dāng)前位置存儲(chǔ)在url的hash部分(http://example.com/#/your/page.),不需要服務(wù)器增加特殊配置

          路由匹配組件Route和Switch

          Switch組件搜索其下路由Route組件,渲染第一個(gè)匹配到的路由而忽略其他 Route為視圖渲染出口


          ??<Route?path={`${match.path}/:topicId`}>
          ????<Topic?/>
          ??Route>

          ??<Route?path={match.path}>
          ????<h3>Please?select?a?topic.h3>

          ??Route>
          </Switch>

          導(dǎo)航組件Link,NavLink和Redirect

          Link組件用來在應(yīng)用中創(chuàng)建鏈接。Link會(huì)被渲染成a標(biāo)簽


            ??<li>
            ????<Link?to={`${match.url}/components`}>ComponentsLink>

            ??li>
            ??<li>
            ????<Link?to={`${match.url}/props-v-state`}>
            ??????Props?v.?State
            ????Link>

            ??li>
            </ul>

          NavLink是一種特殊類型的Link,支持自動(dòng)添加active class

          "/react"?activeClassName="hurray">
          ??React
          </NavLink>

          /
          /?When?the?URL?is?/react,?this?renders:
          //?React

          //?When?it's?something?else:
          //?React

          任何時(shí)候你想強(qiáng)制導(dǎo)航,你可以渲染一個(gè)Redirect組件。當(dāng)渲染時(shí),它將使用其來支持導(dǎo)航

          "/login"?/>

          代碼分割

          即code-splitting, 網(wǎng)頁的增量下載, 未使用到的包不會(huì)加載 我們使用webpack, @babel/plugin-syntax-dynamic-import, 和 loadable-components來實(shí)現(xiàn)代碼分割 首先安裝依賴包

          yarn?add?@babel/preset-react?@babel/plugin-syntax-dynamic-import?loadable-components?--dev

          配置.babelrc文件(沒有的話在項(xiàng)目根目錄下新建一個(gè))

          {
          ??"presets":?["@babel/preset-react"],
          ??"plugins":?["@babel/plugin-syntax-dynamic-import"]
          }

          修改App.js

          import?React?from?"react";
          import?{?BrowserRouter?as?Router,?Route,?Switch?}?from?"react-router-dom";
          import?loadable?from?"@loadable/component";
          import?Loading?from?"../components/Loading";
          import?"./App.css";

          const?Counter?=?loadable(()?=>?import("../features/counter/Counter"),?{
          ??fallback:?<Loading?/>,
          });
          const?Book?=?loadable(()?=>?import("../features/book/Book"),?{
          ??fallback:?<Loading?/>,
          });

          function?App()?{
          ??return?(
          ????<Router>
          ??????<Switch>
          ????????<Route?exact?path="/"?component={Counter}?/>
          ????????<Route?path="/book"?component={Book}?/>
          ??????Switch>

          ????Router>
          ??);
          }

          export?default?App;

          滾動(dòng)狀態(tài)恢復(fù)

          當(dāng)路由切換時(shí)候頁面自動(dòng)滾動(dòng)到頂部或者恢復(fù)滾動(dòng)位置

          import?{?useEffect?}?from?"react";
          import?{?useLocation?}?from?"react-router-dom";

          export?default?function?ScrollToTop()?{
          ??const?{?pathname?}?=?useLocation();

          ??useEffect(()?=>?{
          ????window.scrollTo(0,?0);
          ??},?[pathname]);

          ??return?null;
          }

          不使用Hook(v16.8以上才能夠使用), 可以使用react-router-dom提供的withRouter高階函數(shù)

          import?React?from?"react";
          import?{?withRouter?}?from?"react-router-dom";

          class?ScrollToTop?extends?React.Component?{
          ??componentDidUpdate(prevProps)?{
          ????if?(
          ??????this.props.location.pathname?!==?prevProps.location.pathname
          ????)?{
          ??????window.scrollTo(0,?0);
          ????}
          ??}

          ??render()?{
          ????return?null;
          ??}
          }

          export?default?withRouter(ScrollToTop);

          重要API的適應(yīng)

          BrowserRouter

          基于H5 History接口的路由

          ??basename={optionalString}????
          ??forceRefresh={optionalBool}???
          ??getUserConfirmation={optionalFunc}
          ??keyLength={optionalNumber}???
          >
          ??<App?/>
          </BrowserRouter>

          HashRouter

          使用URL的哈希部分(例如window.location.hash)來保持你的UI與URL同步。

          ??basename={optionalString}??
          ??getUserConfirmation={optionalFunc}
          ??hashTpe={optionalString}??
          >
          ??<App?/>
          </HashRouter>

          Link

          聲明式路由組件

          "/about">About</Link>
          • to 導(dǎo)向哪個(gè)路由,可以為字符串,也可以為一個(gè)對(duì)象或者函數(shù)
          "/courses?sort=name"?/>
          ???to={{
          ?????pathname:?"/courses",????//?路徑
          ?????search:?"?sort=name",??//?查詢參數(shù)
          ?????hash:?"#the-hash",???//?hash值
          ?????state:?{?fromDashboard:?true?}??//?持久化到location的狀態(tài)數(shù)據(jù)
          ???}}
          ?/>

          一個(gè)函數(shù),當(dāng)前位置作為參數(shù)傳遞給它,并且應(yīng)該以字符串或?qū)ο蟮男问椒祷匚恢帽硎?/p>

          ?({?...location,?pathname:?"/courses"?})}?/>
          ?`${location.pathname}?sort=name`}?/>

          其他可用屬性

          • replace: 當(dāng)為true時(shí),單擊該鏈接將替換歷史堆棧中的當(dāng)前條目,而不是添加一個(gè)新條目。
          • innerRef 值為函數(shù)
          ??to="/"
          ??innerRef={node?=>?{
          ????//?node指向掛載的dom元素,?卸載時(shí)候?yàn)閚ull
          ??}}
          />

          值為Ref對(duì)象

          let?anchorRef?=?React.createRef()

          "/"?innerRef={anchorRef}?/>
          • component 定制化自己的導(dǎo)航組件
          const?FancyLink?=?React.forwardRef((props,?ref)?=>?(
          ??<a?ref={ref}?{...props}>???{props.children}a>
          ))

          "/"?component={FancyLink}?/>

          title, id, className等a標(biāo)簽接受的屬性

          NavLink

          是 Link 的一個(gè)特殊版本,當(dāng)呈現(xiàn)的元素與當(dāng)前URL匹配時(shí),它將向該元素添加樣式屬性。

          activeClassName 當(dāng)元素處于active狀態(tài)時(shí),類將提供該class。默認(rèn)的給定class是active。這將與className樣式疊加

          activeStyle 內(nèi)嵌方式聲明active狀態(tài)樣式

          exact 布爾類型, 為true是路徑完全匹配才會(huì)添加active class

          strict 路徑匹配是否嚴(yán)格, 為true的話結(jié)尾的斜杠會(huì)被考慮

          isActive函數(shù), 可以自定義active class添加邏輯

          ??to="/events/123"
          ??isActive={(match,?location)?=>?{
          ????if?(!match)?{
          ??????return?false;
          ????}

          ????//?only?consider?an?event?active?if?its?event?id?is?an?odd?number
          ????const?eventID?=?parseInt(match.params.eventID);
          ????return?!isNaN(eventID)?&&?eventID?%?2?===?1;
          ??}}
          >
          ??Event?123
          </NavLink>

          Redirect

          重定向

          "/">
          ??{loggedIn???<Redirect?to="/dashboard"?/>?:?<PublicHomePage?/>}
          </Route>

          to也可以為對(duì)象

          ??to={{
          ????pathname:?"/login",
          ????search:?"?utm=your+face",
          ????state:?{?referrer:?currentLocation?}
          ??}}
          />

          push屬性: 當(dāng)為真時(shí),重定向?qū)岩粋€(gè)新的條目推送到歷史中,而不是取代當(dāng)前的條目。from屬性: 要重定向的路徑名。路徑-regexp@^1.7.0能夠理解的任何有效URL路徑。在to中為模式提供了所有匹配的URL參數(shù)。必須包含to中使用的所有參數(shù)。不被to使用的其他參數(shù)將被忽略。


          ??<Redirect?from="/old-path"?to="/new-path"?/>
          ??<Route?path="/new-path">
          ????<Place?/>
          ??Route>

          </Switch>

          /
          /?Redirect?with?matched?parameters

          ??sers/:id"?to="/users/profile/:id"?/>
          ??/users/profile/:id">
          ????
          ??

          exact屬性, 路徑是否完全匹配

          strict屬性:路徑匹配是否嚴(yán)格,區(qū)分斜杠

          sensitive屬性: 路徑匹配是否大小寫敏感

          Route

          路由組件可能是反應(yīng)路由器中最重要的組件,了解和學(xué)習(xí)使用好。它最基本的職責(zé)是在路徑與當(dāng)前URL匹配時(shí)呈現(xiàn)某個(gè)UI

          route component

          只有路由匹配才會(huì)掛載component指定的組件

          ReactDOM.render(
          ??<Router>
          ????<Route?path="/user/:username"?component={User}?/>
          ??Router>
          ,
          ??node
          );

          render func

          路由匹配函數(shù)就會(huì)調(diào)用

          ReactDOM.render(
          ??<Router>
          ????<Route?path="/home"?render={()?=>?<div>Homediv>
          }?/>
          ??Router>,
          ??node
          );

          children func

          不管路由是否匹配都會(huì)渲染對(duì)應(yīng)組件

          import?React?from?"react";
          import?ReactDOM?from?"react-dom";
          import?{
          ??BrowserRouter?as?Router,
          ??Link,
          ??Route
          }?from?"react-router-dom";

          function?ListItemLink({?to,?...rest?})?{
          ??return?(
          ????<Route
          ??????path={to}
          ??????children={({?match?})?=>
          ?(
          ????????<li?className={match???"active"?:?""}>
          ??????????<Link?to={to}?{...rest}?/>
          ????????li>

          ??????)}
          ????/>
          ??);
          }

          ReactDOM.render(
          ??<Router>
          ????<ul>
          ??????<ListItemLink?to="/somewhere"?/>
          ??????<ListItemLink?to="/somewhere-else"?/>
          ????ul>

          ??Router>,
          ??node
          );

          上面的例子中如果路徑匹配的話會(huì)渲染帶有active class的li 當(dāng)添加動(dòng)畫過渡效果時(shí)候children屬性也很有用

          ??children={({?match,?...rest?})?=>?(
          ????{/*?Animate?will?always?render,?so?you?can?use?lifecycles
          ????????to?animate?its?child?in?and?out?*/
          }
          ????
          ??????{match?&&?<Something?{...rest}/>}
          ????</Animate>
          ??)}
          /
          >

          幾個(gè)重要變量

          location

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

          location會(huì)出現(xiàn)在下面幾個(gè)地方

          • Route component(路由組件)中使用 this.props.location
          • Route組件的 render函數(shù) as ({ location }) => ()
          • Route組件的children屬性 as ({ location }) => ()
          • withRouter高階函數(shù)包裹的組件中使用 as this.props.location

          match

          一個(gè)說明路由為何匹配的對(duì)象,包含路由跳轉(zhuǎn)參數(shù)params, 是否精確匹配isExact, 路徑path, url

          • 路由組件(Route component)中使用this.props.match
          • 路由render函數(shù)中解構(gòu)出match對(duì)象Route render as ({ match }) => ()
          • 路由children函數(shù)中解構(gòu)出match對(duì)象Route children as ({ match }) => ()
          • withRouter高階函數(shù)包裹組件中使用 this.props.match
          • matchPath
          • useRouteMatch

          可以基于此來實(shí)現(xiàn)路由嵌套

          import?{?Link,?Switch,?Route?}?from?"react-router-dom";
          import?{?useRouteMatch?}?from?"@/utils";
          export?default?function?NestRoute()?{
          ??const?{?path,?url?}?=?useRouteMatch("/demo");
          ??return?(
          ????<>
          ??????<h3>路由嵌套h3>

          ??????<ul>
          ????????<li>
          ??????????<Link?to={`${url}/demo1`}>demo1Link>
          ????????li>
          ????????<li>
          ??????????<Link?to={`${url}/demo2`}>demo2Link>
          ????????li>
          ??????ul>
          ??????<Switch>
          ????????<Route?path="/demo"?exact>
          ??????????請(qǐng)選擇一個(gè)實(shí)例
          ????????Route>
          ????????<Route
          ??????????path={`${path}/:demoId`}
          ??????????render={({?match?})?=>
          ?<h1>{match.params.demoId}h1>}
          ????????>Route>
          ??????Switch>
          ????
          ??);
          }

          history

          路由歷史對(duì)象,包含以下屬性

          • length - (number) 歷史堆棧中的條目數(shù)
          • action - (string) 當(dāng)前動(dòng)作類型 (PUSH, REPLACE, or POP)
          • location - (object) 當(dāng)前的location對(duì)象,可能包含以下屬性:
          • pathname - (string) URL的path部分
          • search - (string) URL的query部分
          • hash - (string) URL hash部分
          • state - (object)位置特定的狀態(tài),當(dāng)此位置被推入堆棧時(shí)提供的推入狀態(tài)(路徑、狀態(tài))。僅在瀏覽器和內(nèi)存歷史中可用.
          • push(path, [state]) - (function) 將新條目推入歷史堆棧
          • replace(path, [state]) - (function)替換歷史堆棧上的當(dāng)前條目
          • go(n) - (function) 在歷史堆棧中移動(dòng)n(可正可負(fù),即向前或者向后)個(gè)條目的指針
          • goBack() - (function) 等價(jià)于go(-1), 后退一頁
          • goForward() - (function) 等價(jià)于 go(1), 前進(jìn)一頁

          歷史對(duì)象是可變的。因此,建議從渲染道具中訪問位置,而不是從history.location中訪問

          常用Hooks

          react >= 16.8

          useHistory

          import?{?useHistory?}?from?"react-router-dom";

          function?HomeButton()?{
          ??let?history?=?useHistory();

          ??function?handleClick()?{
          ????history.push("/home");
          ??}

          ??return?(
          ????<button?type="button"?onClick={handleClick}>
          ??????Go?home
          ????button>

          ??);
          }

          useLocation

          獲取位置對(duì)象

          ??let?location?=?useLocation();

          useParams

          useParams返回一個(gè)包含URL參數(shù)的鍵/值對(duì)的對(duì)象。使用它來訪問match。當(dāng)前的參數(shù)。

          import?React?from?"react";
          import?ReactDOM?from?"react-dom";
          import?{
          ??BrowserRouter?as?Router,
          ??Switch,
          ??Route,
          ??useParams
          }?from?"react-router-dom";

          function?BlogPost()?{
          ??let?{?slug?}?=?useParams();
          ??return?<div>Now?showing?post?{slug}div>;
          }

          ReactDOM.render(
          ??<Router>
          ????<Switch>
          ??????<Route?exact?path="/">
          ????????<HomePage?/>
          ??????Route>

          ??????<Route?path="/blog/:slug">
          ????????<BlogPost?/>
          ??????Route>
          ????Switch>
          ??Router>,
          ??node
          );

          useRouteMatch

          useRouteMatch鉤子嘗試以與相同的方式匹配當(dāng)前URL。它主要用于在不實(shí)際呈現(xiàn)的情況下訪問匹配數(shù)據(jù)

          import?{?Route?}?from?"react-router-dom";

          function?BlogPost()?{
          ??return?(
          ????<Route
          ??????path="/blog/:slug"
          ??????render={({?match?})?=>
          ?{
          ????????//?Do?whatever?you?want?with?the?match...
          ????????return?<div?/>;
          ??????}}
          ????/>

          ??);
          }
          使用useRouteMatch的話就可以不實(shí)際渲染出
          import?{?useRouteMatch?}?from?"react-router-dom";

          function?BlogPost()?{
          ??let?match?=?useRouteMatch("/blog/:slug");

          ??//?Do?whatever?you?want?with?the?match...
          ??return?<div?/>;
          }?

          路由傳參

          通配符傳參

          Route定義方式:

          '/path/:name'?component={Path}/>???

          Link組件:

          "/path/通過通配符傳參">通配符</Link>???

          參數(shù)獲取:

          this.props.match.params.name???

          優(yōu)點(diǎn):簡單快捷,并且,在刷新頁面的時(shí)候,參數(shù)不會(huì)丟失。

          缺點(diǎn):只能傳字符串,并且,如果傳的值太多的話,url會(huì)變得長而丑陋。

          如果,你想傳對(duì)象的話,可以用JSON.stringify(),想將其轉(zhuǎn)為字符串,然后另外的頁面接收后,用JSON.parse()轉(zhuǎn)回去。

          query

          Route定義方式:

          '/query'?component={Query}/>???

          Link組件:

          var?query?=?{
          ??pathname:?'/query',
          ??querthis.props.location.query
          y:?'我是通過query傳值?'
          }?
          query</Link>

          參數(shù)獲取:

          this.props.location.query
          ???

          優(yōu)點(diǎn):優(yōu)雅,可傳對(duì)象 缺點(diǎn):刷新頁面,參數(shù)丟失

          state傳參

          Route定義方式:

          state</Link>
          ???

          Link組件:

          var?state?=?{
          ??pathname:?'/state',
          ??state:?'我是通過state傳值'
          ?}
          ?'/state'?component={State}/>
          ???

          參數(shù)獲取:

          this.props.location.state???

          優(yōu)點(diǎn):優(yōu)雅,可傳對(duì)象 缺點(diǎn):刷新頁面,參數(shù)丟失

          參考

          https://reactrouter.com/web/guides/quick-start???



          瀏覽 120
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久草色香蕉 | 国产精品国产精品国产专区不片 | 无码AV电影| 国产女人水真多18精品 | 日韩av在线影音先锋 |