什么是 react-router 及实现方式
ract-router
- 不同的路径渲染不同的组件
指定一个 Route 组件要渲染的内容,有三种方式:
- component 属性,值是一个组件的类型,他不能写定义的逻辑
<Route path='/home' component={Home}></Route>
- render 属性,它是一个函数,如果路径匹配的话,就要渲染它这个函数的返回值
<Route path='/' render={() => <h2>world</h2>}></Route>
- children 属性,它也是一个函数
实现方式,有两种:
- HashRouter:利用 hash 实现路由切换
- BrowserRouter:实现 H5 Api 路由的切换
- 两种实现方式其内部都是调用了 react-router 库中的router,只不过分别传入了不同的 history 对象
HashRouter
- 利用 hash 实现路由切换
- hashchange:每当 hash 值发生变化的话,就会执行回调函数
- window.location.hash:获取 hash
- 当前 router 提供的内置组件
- HashRouter
- Router:渲染容器,只有一个
- Route:路由规则
- 使用 HashRouter 把根组件包裹起来「只包裹在最外层即可」,谁用到了组件,包裹谁的根组件
- 参数
- path:指定路径,一个路径对应一个组件
- component:要展示的组件,只是展示页面渲染
- render:函数体返回的组件
<Route path='/' render={() =>
world
}> - 如果存在逻辑判断,使用 render
- 只要路径上包含:/,都会渲染到页面上
- route 会从上到下依次匹配,匹配到则渲染,路径匹配不上的都显示为空标签
- 页面的路径跟谁能匹配上,该行代码就会被替换成相应的组件
- exact:精确匹配,只有完全跟路径匹配的情况下才会渲染
<HashRouter>
<Route path='/home' exact component={Home}></Route>
<HashRouter/>
- 链接上会多一个:# 号,# 号后面都称为 hash
- hash 的特点:hash 改变页面不会刷新
- 渲染组件时交给了 Route 来处理,它会默认给我们传递一些参数:根据路径的匹配传递参数
- history:放的一些方法「push、replace」
- location:原生方法一样
- match:匹配到路径的信息
- isExact
- params
- path
- url
<HashRouter>
<Route exact={true} path="/" component={Home} />
<Route path="/User" component={Home} />
</HashRouter>
BrowserRouter
- 利用 H5 API 实现路由的切换
- html5 History API 包括两个方法:history.pushState() 和 history.replaceState(),和一个事件 window.onpopstate
- history.pushState(stateObject, title, url)
- 第一个参数:存储 URL 对应的状态对象,该对象可在onpopstate 事件中获取,也可以在 history 对象中获取
- 第二个参数:标题,目前浏览器并未实现
- 第三个参数:设定的 URL
- pushState 函数向浏览器的历史堆栈中压入一个 URL 为设定值的记录,并改变历史堆栈的当前指针至栈顶
- history.replaceState()
- 参数与 pushState 相同,含义也相同
- 唯一的区别在于 replaceState 是替换浏览器历史堆栈的,当前历史记录为设定的 URL
- replaceState 不会改动浏览器历史隧站的当前指针
- window.onpopstate
- window 的属性
- 该事件会在调用浏览器的前进、后退以及执行 history.forward、history.back 和 history.go 触发,这些操作都会修改历史堆栈的当前指针,History 栈是不会变的
- 在不改变 document 的前提下,一旦当前指针改变则会触发 onpopstate 事件
- history.pushState(stateObject, title, url)
Switch 组件:优化性能
- switch 包起来的 Route 只要有一个匹配上了,下边就不在匹配
- 使用 switch 不能用元素包裹起来
<Switch>
<Redirect path='/' exact to='/home'></Redirect>
<Route path='/qq' render={(props) => GetQuery(QQ, props)}></Route>
<Route path='/login' component={Login}></Route>
<Route path='/*' render={() => <NoFound />}></Route>
</Switch>
Redirect:路由重定向
- 如果所有路由都没有匹配到的话,会执行 Redireact
- Redireact 必须配合 Switch 使用
- 参数
- path:匹配到重定向的路径
- to:重定向到哪个组件
<Switch>
<Redirect path='/' exact to='/home'></Redirect>
<Route path='/login' component={Login}></Route>
<Redirect path='/' exact to='/home'></Redirect>
</Switch>
Link
- 用来生成点击跳转:a 标签
- 用 Link 组件必须结合 to 属性来使用,会渲染成可以点击跳转的标签
- 参数:to 就是跳到哪里
- 使用方法
<Link to="/home"><Link/>
路由嵌套
- 哪个组件下的路由嵌套,就在哪个组件文件下进行路由嵌套即可
- 示例 在 home 组件中嵌套路由
<Route path='/home/a' component={MyA}></Route>
<Route path='/home/b' component={MyB}></Route>
受保护的路由
- 比如:登录之后可以跳转显示的页面
- 登录之后可以访问 user,否则跳转到 login
- 使用方法
<Protect path='/user' component={User} level={4}></Protect>
NavLink 组件
- 可点击跳转的标签,自动添加 class 类名:active
路径404
- 路径都匹配不上的话,展示 404
<Route path='/*' render={() => <NoFound />}></Route>
withRouter
实现原理
- 创建一个 routerContext 文件
import React from 'react'
const RouterContext = React.createContext();// 创建一个全局上下文
export default RouterContext;
- 根组件进行赋值
<RouterContext.Provider value={// 传给子组件的值}>
{this.props.children}// 儿子们
</RouterContext.Provider>
- 创建一个处理组件的 js 文件,最终返回一个被 RouterContext.Consumer 包裹的新组件
import RouterContext from '../routerContext'
function withRouter(OldComponent) {
return props=>{
<RouterContext.Consumer>
{
value=>{
return <OldComponent {...props} {...value}>
}
}
</RouterContext.Consumer>
}
}
- 经过处理后,儿子们都可以拿到 props 中的属性,比如:history、location...
Prompt:弹出框
- 使用场景:编辑文字,如果输入框中有值,值不为空,就需要阻止,否则不阻止
- 属性:
- when 属性:true 阻止,false 不阻止
- message:提示内容
路由 hooks
- 直接调用相应的 hook,便可获取 props 中相应的属性及值
- useHistory
- useLocation
- useParams
组件懒加载
插件:react-loadable