React 路由 封裝
React 路由 封裝
鴿了一段時間,終於迴歸React的陣營中,後面會完整製作一個專案,今天先講一下路由,後續會和專案一併講解。
主要目錄
我發現很多博主講封裝,一是轉載別人的,二又不說明 哪個打哪個檔案的程式碼,雲裡霧裡。
我們一般把 頁面元件(頁面)放到 component 裡面的 pages 裡,相當於 vue 的 view檔案,因為在React裡面,頁面也算是元件,所以,pages 理應放到 component 裡面。
我們每建立一個頁面都必須先建立資料夾,然後建立 index.js/index.jsx ,這樣既方便我們新增單獨頁面的樣式(如,在Index檔案裡建立多一個index.css),又方便我們新增頁面的 子頁面(如Test)。
router檔案中,
config.jsx 用於存放我們的路由列表,
index.jsx 是路由元件的入口
router-view.jsx 是我們每一個 Router 的封裝,後面會講到。
路由列表
config.jsx
import { lazy } from 'react'
const routes = [
{
path: '/test',
component: lazy(() => import('../pages/Test')),
meta: {
title: '測試頁面'
},
// 若有子頁面,此為參考
routes: [
{
path: '/test/demo',
component: lazy(() => import('../pages/Test/Demo'))
},
{
path: '/test/demo2',
component: lazy(() => import('../pages/Test/Demo2'))
}
]
},
{
path: '/index',
component: lazy(() => import('../pages/Index')),
// 如果要求嚴格路徑
isExact: true,
meta: {
title: '首頁'
}
},
{
path: '/login',
component: lazy(() => import('../pages/Login')),
meta: {
title: '登入頁面'
}
},
{
path: '/',
component: lazy(() => import('../pages/Index')),
meta: {
title: '首頁'
}
},
{
path: null,
redirect: lazy(() => import('../pages/NotFound')),
meta: {
title: '404'
}
},
]
export default routes
這裡儘量做得與vue路由格式一樣
lazy嘛,顧名思義懶載入
寫這個路由列表,目的只是為了後期方便新增修改頁面
index.jsx
import React from 'react'
import routes from './config' // 路由列表,有其他的路由列表頁面可以繼續引入
import RouterView from './router-view' // 封裝好的 Router
const routerList = [ // 將所有路由拼接在一起
...routes
]
const ViewRouter = () => {
return (
<div>
<RouterView route={routerList} /> // 呼叫封裝好的 Router
</div>
)
}
export default ViewRouter
我們的目的是將繁瑣的路由封裝成類似於 vue 的 <view-router />
一樣簡單實用
router-view.jsx
import {
Switch,
Redirect,
Route
} from "react-router-dom"; // 引入 react-router-dom
import { Suspense } from 'react' // Suspense 配合前面的 laze() 使用,不加上會報錯
const RouterView = (props) => {
let { route } = props // 拿到index.jsx頁面傳過來的 路由列表
return (
<Suspense fallback={<div>Loading...</div>}> // 載入時的dom
<Switch>
{
route.map((item, index) => {
return item.component ? <Route key={index} path={item.path} render={(props) => {
return <item.component route={item.routes} {...props} />
}}></Route> : <Redirect key={index} from={item.path} to={item.redirect} /> // 找不到對應的路由時 全部去到404頁面
})
}
</Switch>
</Suspense>
)
}
export default RouterView
這邊 首先通過 map() 遍歷 Route ,按照路由表格式傳遞引數。這裡用 render 而不是直接 component={} ,是因為我們可能有 巢狀子頁面的需求。一樣的,把routes (根據路由表的子頁面list)傳進去,這樣就完成了整個 Route 的封裝,無論我們有多少個巢狀子頁面,都可以直接使用。
正常來說,我們得先建立頁面,不然,路由頁面那邊會報錯,那麼我們就把頁面簡單過一下:
Index/index.jsx
import React, { Component } from 'react'
export default class index extends Component {
goRouter = (path) => {
return () => {
this.props.history.push({
pathname: path,
state: null
})
}
}
render() {
return (
<div>
<h3>index頁面</h3>
<div onClick={this.goRouter('/login')}>Go Login</div>
</div>
)
}
}
這裡說一下跳轉,react的跳轉不僅侷限於 Link/NavLink 的跳轉,我們在高階函式裡,通過 this.props.history.push()【帶痕跡】/ this.props.history.replace()【痕無跡】
Login/index.jsx
import React, { Component } from 'react'
export default class login extends Component {
goRouter = (path) => {
return () => {
this.props.history.push({
pathname: path,
state: null
})
}
}
render() {
return (
<div>
<h3>login頁面</h3>
<div onClick={this.goRouter('/index')}>Go Index</div>
</div>
)
}
}
NotFound/index.jsx
import React, { Component } from 'react'
export default class NotFound extends Component {
render() {
return (
<div>
404
</div>
)
}
}
404頁面按自己的來
Test/index.jsx
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom'
import RouterView from '../../router/router-view'
export default class test extends Component {
render() {
let {route} = this.props
return (
<div>
<br />
這是測試頁面
<br />
<br />
<NavLink to="/test/demo">demo</NavLink>
<NavLink to="/test/demo2">demo2</NavLink>
<br />
<br />
<RouterView route={route} />
</div>
)
}
}
test頁面是為了讓大家更好理解 巢狀子頁面做的一個例子
因為Text/idnex.jsx 頁面本身就是個頁面元件,我們在 router-view.jsx 頁面裡就已經往裡面傳了 route
return <item.component route={item.routes} {...props} />
所以我們是可以直接在 Text/index.jsx裡面 直接拿到route
let {route} = this.props
所以我們直接引用
import RouterView from '../../router/router-view'
並呼叫即可
<RouterView route={route} />
Text/Demo/index.jsx
import React, { Component } from 'react'
export default class demo extends Component {
render() {
return (
<div>
<h2>這是測試頁面的子頁面測試</h2>
</div>
)
}
}
Text/Demo2/index.jsx
import React, { Component } from 'react'
export default class demo2 extends Component {
render() {
return (
<div>
<h2>這是測試頁面的子頁面測試2</h2>
</div>
)
}
}
在App.jsx頁面引用路由元件
慣例先上程式碼
App.jsx
import { NavLink } from 'react-router-dom'
import ViewRouter from './router/index' // 封裝好的路由
import './App.css';
function App() {
return (
<div className="App">
<div className="nar">
<NavLink to="/index">Index</NavLink>
<NavLink to="/login">Login</NavLink>
<NavLink to="/test">test</NavLink>
</div>
<div className="content">
<ViewRouter />
</div>
</div>
);
}
export default App;
就是一個引入並呼叫
注意
我們的路由是被 整個 BrowserRouter包裹起來才能生效,所以我們最後一步,直接在 index.js 頁面加上
import React from 'react';
import ReactDOM from 'react-dom';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter as Router } from 'react-router-dom' // BrowserRouter
import App from './App';
ReactDOM.render(
<Router> // 直接把整個App包裹起來
<App />
</Router>,
document.getElementById('root')
);
reportWebVitals();
搞定。。。。。。。
有問題請留言,因為程式碼量少,所以沒有原始碼下載