# Hello
路由是根据不同的网址显示不同的组件,并有一系列API的封装
import React from 'react';
import { HashRouter as Router, Link, Route } from "react-router-dom"
const Home = () => <h1>首页</h1>;
const Prod = () => <h1>产品</h1>;
const User = () => <h1>用户</h1>;
function App() {
return (
<>
<Router>
<Link to="/">首页</Link>
<Link to="/pro">产品</Link>
<Link to="/user">用户</Link>
<Route path="/" exact component={Home} />
<Route path="/pro" component={Prod} />
<Route path="/user" component={User} />
</Router>
</>
)
}
export default App;
Link 的 to 属性就是要跳转的路由
Rote 中的 path 对应 to ,表示要渲染的组件
exact 表示完全匹配,如果没有,那么 / 或匹配 /* 而不是 /
# Router
组成
BrowserRouter
HashRouter
MemoryRouter
NativeRouter
StaticRouter
其中 BrowserRouter 和 HashRouter 属于浏览器路由
浏览器路由
BrowserRouter 的路由类似 http://localhost:3000/user
HashRouter 的路由类似 http://localhost:3000/#/user
属性
pathname 路由的地址其实是 pathname + path
比如 Router 加上 pathname="api"
使用前:http://localhost:3000/#/user
使用后:http://localhost:3000/#/api/user
<Router basename="/api">
<Link to="/">首页</Link>
<Link to="/pro">产品</Link>
<Link to="/user">用户</Link>
<Route path="/" exact component={Home} />
<Route path="/pro" component={Prod} />
<Route path="/user" component={User} />
</Router>
forceRefresh 布尔值,是否刷新整个页面,如果为 true ,每次跳转路由都会刷新页面
<Router forceRefresh={true}>
<Link to="/">首页</Link>
<Link to="/pro">产品</Link>
<Link to="/user">用户</Link>
<Route path="/" exact component={Home} />
<Route path="/pro" component={Prod} />
<Route path="/user" component={User} />
</Router>
getUserConfirmation 当导航需要确认时执行的函数,需配合 Prompt 使用
Prompt 写在需要提示的路由中,也可不写 getUserConfirmation ,如果不写,默认是window弹框
写了 getUserConfirmation 后,可以在处理跳转前的逻辑
import React from 'react';
import { HashRouter as Router, Link, Route, Prompt } from "react-router-dom"
const Home = () => <h1>首页<Prompt message="您是否离开首页?"></Prompt></h1>;
const Prod = () => <h1>产品</h1>;
const User = () => <h1>用户</h1>;
const getConfirmation = (message, callback) => {
const allowTransition = window.confirm(message)
callback(allowTransition)
}
function App() {
return (
<>
<Router getUserConfirmation={getConfirmation}>
<Link to="/">首页</Link>
<Link to="/pro">产品</Link>
<Link to="/user">用户</Link>
<Route path="/" exact component={Home} />
<Route path="/pro" component={Prod} />
<Route path="/user" component={User} />
</Router>
</>
)
}
export default App;
hashType HashRouter独有,一共有三个值
slash #/api/user
noslash #api/user
hashbang #!/api/user
# Link
属性 to
路由跳转地址,可以是字符串
<Link to="/user">用户</Link>
可是是对象
<Link to={{
pathname:"/user"
}}>用户</Link>
对象有如下属性:
pathname 跳转地址
search 参数传递
hash 跳转的锚点
state 状态,可以通过 params.location.state 获取
const User = (params) => {
return params.location.state ? <h1>{params.location.state.name}</h1> : null;
}
属性 replace
布尔值,如果为 true,则访问历史替换原地址
如果为false(默认),访问历史记录添加一项
<Link to="/user" replace />
# NavLink
特殊的 Link
如果在当前路由状态,会默认的添加一个 active 样式
属性:
activeStyle 如果在当前路由状态,可以添加额外的style
activeClassName 如果在当前路由状态,可以添加额外的 class 并替换 active
exact 完全匹配 activeStyle 和 activeClassName 才会生效
# Route
三种使用方式
使用component,默认把参数传到组件中
<Link to="/">首页</Link>
const Home = (props) => {
console.log(props);
return <h1>首页</h1>;
}
使用 render ,需自行把参数添加到组件中
const Prod = (props) => {
console.log(props);
return <h1>产品</h1>;
}
<Route path="/pro" render={(props) => <Prod {...props}></Prod>} />
使用 children,每次都会执行,有一个参数 match 可以判断是否是指定路由
const User = (props) => {
console.log(props);
return <h1>用户</h1>;
}
<Route path="/user" children={(props) => {
return props.match ? <User {...props}></User> : null;
}} />
match
先看一下 match 的结构
{
isExact: true,
params: { id: "2" },
path: "/pro/:id",
url: "/pro/2"
}
isExact 是否全匹配
params 参数
path 匹配路径格式
url 匹配路径
作用一: 路由参数
可以使用 props.match.params 获取参数
import React from 'react';
import { HashRouter as Router, Link, Route } from "react-router-dom"
const Home = () => <h1>首页</h1>;
const User = () => <h1>用户</h1>;
const ProdDetail = (props) => <p>产品:{props.match.params.id}</p>;
const Prod = () => {
return (
<>
<Link to="/pro/1">产品1</Link>
<Link to="/pro/2">产品2</Link>
<Link to="/pro/3">产品3</Link>
<Route path="/pro/:id" component={ProdDetail}></Route>
</>
)
}
function App() {
return (
<>
<Router basename="/api">
<Link to="/">首页</Link>
<Link to="/pro">产品1</Link>
<Link to="/user">用户</Link>
<Route path="/" component={Home} exact />
<Route path="/pro" component={Prod} />
<Route path="/user" component={User} />
</Router>
</>
)
}
export default App;
作用二:变量提取
const Prod = (props) => {
const basePath = props.match.url;
return (
<>
<Link to={`${basePath}/1`}>产品1</Link>
<Link to={`${basePath}/2`}>产品2</Link>
<Link to={`${basePath}/3`}>产品3</Link>
<Route path={`${basePath}/:id`} component={ProdDetail}></Route>
</>
)
}
location
可以拿到 Link:to 中的内容,如果是字符串则拿不到 state
<Link to={
{
pathname: "/user",
hash: "#h1",
search: "?name=lisi",
state: { name: "张三" }
}
}>用户</Link>
const User = ({ location }) => {
console.log(location);
return <h1>用户</h1>;
}
// 得到的结果为
{
hash: "#h1",
pathname: "/user",
search: "?name=lisi",
state: { name: "张三" }
}
history
操作路由的一些 API ,可以从传递的参数中解构获取
const User = ({ history }) => {
console.log(history);
return <h1>用户</h1>;
}
属性:
length 堆栈数量
action 当前动作,是跳转过来的(PUSH),还是切换过来的(REPLACE)还是移出的(POP)
方法:
push 跳转路由
replace 替换栈顶路由
go 前进或后退多少路由
goBack 后退1步,相当于 go(-1)
goForward 前进一步,相当于 go(1)
block 阻止跳转
# Redirect
重定向到新的地址
import React from 'react';
import { HashRouter as Router, Link, Route, Redirect } from "react-router-dom"
const Home = () => <h1>首页</h1>;
const Prod = () => <h1>产品</h1>;
const User = () => <Redirect to="/pro"></Redirect>;
function App() {
return (
<>
<Router basename="/api">
<Link to="/">首页</Link>
<Link to="/pro">产品</Link>
<Link to="/user">用户</Link>
<Route path="/" component={Home} exact />
<Route path="/pro" component={Prod} />
<Route path="/user" component={User} />
</Router>
</>
)
}
export default App;
此时点用户,会被重定向到产品路由
常用作配合状态使用,当状态更新时,重定向到其他路由,比如登出
import React, { useState } from 'react';
import { HashRouter as Router, Link, Route, Redirect } from "react-router-dom"
const Home = () => {
const [isLogin, setisLogin] = useState(true);
return (
isLogin ?
<>
<h1>恭喜xx登录成功!</h1>
<p onClick={() => setisLogin(false)}>登出</p>
</> :
<Redirect to="/login"></Redirect>
)
};
const Login = () => {
return (
<>
<h1>登录页</h1>
<button>登录</button>
</>
)
};
function App() {
return (
<>
<Router basename="/api">
<Link to="/">首页</Link>
<Route path="/" component={Home} exact />
<Route path="/login" component={Login} />
</Router>
</>
)
}
export default App;
# Switch
未使用 Switch 前,一个地址可以匹配多个路径
比如以下代码,路径 /pro 可匹配 / 和 /pro ,除非给 Route 加上 exact
<>
<Router basename="/api">
<Link to="/">首页</Link>
<Link to="/pro">产品</Link>
<Link to="/user">用户</Link>
<Route path="/" component={Home}></Route>
<Route path="/pro" component={Prod}></Route>
<Route path="/user" component={User}></Route>
</Router>
</>
使用 Switch 之后,只会匹配到遇到的第一个路由
比如以下代码,无论是 / 还是 /pro 还是 /user 都是匹配到了首页
<>
<Router basename="/api">
<Link to="/">首页</Link>
<Link to="/pro">产品</Link>
<Link to="/user">用户</Link>
<Switch>
<Route path="/" component={Home}></Route>
<Route path="/pro" component={Prod}></Route>
<Route path="/user" component={User}></Route>
</Switch>
</Router>
</>
弱匹配的路由放在后面或者加上 exact 属性
<>
<Router basename="/api">
<Link to="/">首页</Link>
<Link to="/pro">产品</Link>
<Link to="/user">用户</Link>
<Switch>
<Route path="/pro" component={Prod}></Route>
<Route path="/user" component={User}></Route>
<Route path="/" component={Home}></Route>
</Switch>
</Router>
</>
Switch 配合 404 页面
<>
<Router basename="/api">
<Link to="/">首页</Link>
<Link to="/pro">产品</Link>
<Link to="/user">用户</Link>
<Switch>
<Route path="/pro" component={Prod}></Route>
<Route path="/user" component={User}></Route>
<Route path="/" component={Home} exact></Route>
<Route component={View404}></Route>
</Switch>
</Router>
</>
# Prompt
组件确认跳转导航,在路由离开之前弹框,如果点击是,则跳转,否则不跳转
import React from 'react';
import { HashRouter as Router, Link, Route, Switch, Prompt } from "react-router-dom"
const Home = () => <h1>Home! <Prompt message="是否离开首页!"></Prompt></h1>;
const User = () => <h1>User!</h1>;
const Prod = () => <h1>Prod!</h1>;
function App() {
return (
<>
<Router basename="/api">
<Link to="/">首页</Link>
<Link to="/pro">产品</Link>
<Link to="/user">用户</Link>
<Switch>
<Route path="/pro" component={Prod}></Route>
<Route path="/user" component={User}></Route>
<Route path="/" component={Home} exact></Route>
</Switch>
</Router>
</>
)
}
export default App;
当首页跳转其他页时,会提示是否离开首页,如果选是,则离开,否则不离开
message 还可以是一个函数,返回结果作为提示语,函数的参数的location
const Home = () => <h1>Home! <Prompt message={
(location) => {
return `是否离开首页,去${location.pathname}`
}
}></Prompt></h1>;
Prompt 还有一个属性,when,默认为 true , 如果为false,则不提示直接跳转
const Home = () => <h1>Home! <Prompt when={false} message={
(location) => {
return `是否离开首页,去${location.pathname}`
}
}></Prompt></h1>;
可以和 getUserConfirmation 配合使用,自定义弹出提示
import React from 'react';
import { HashRouter as Router, Link, Route, Switch, Prompt } from "react-router-dom"
const Home = () => <h1>Home! <Prompt message="是否离开"></Prompt></h1>;
const User = () => <h1>User!</h1>;
const Prod = () => <h1>Prod!</h1>;
const getUserConfirmation = (message, call) => {
const flag = window.confirm(message);
call(flag);
}
function App() {
return (
<>
<Router basename="/api" getUserConfirmation={getUserConfirmation}>
<Link to="/">首页</Link>
<Link to="/pro">产品</Link>
<Link to="/user">用户</Link>
<Switch>
<Route path="/pro" component={Prod}></Route>
<Route path="/user" component={User}></Route>
<Route path="/" component={Home} exact></Route>
</Switch>
</Router>
</>
)
}
export default App;