react之路由
- 功能:让用户从一个视图(组件)导航到另一个视图(组件)
- 前端路由是一套映射规则,在React中,是URL路径与组件的对应关系
- 使用React路由简单来说,就是配置路径和组件
路由的使用
1、安装路由
npm i -S react-router-dom
2、相关组件
-
Router组件:包裹整个应用,一个React应用只需要使用一次
Router: HashRouter和BrowserRouter
- HashRouter: 使用URL的哈希值实现 (localhost:3000/#/first)
- BrowserRouter:使用H5的history API实现(localhost3000/first) -
Link/NavLink组件:用于指定导航链接(a标签)
- to属性:会被编译成 a标签的href属性
to=\'/main\' || to=\'{{pathname=\'/main\'}}\'
- activeClassName属性:指定样式名
- Link 不会显示按钮的高亮显示, NavLink 来替代它
- 最终Link会编译成a标签,
- to属性:会被编译成 a标签的href属性
-
Route组件:指定路由展示组件相关信息(组件渲染)
- path属性:路由规则,这里需要跟Link组件里面to属性的值一致
- exact属性:严格匹配, 为
true
是表示严格匹配,为false
时为正常匹配。 - component属性:展示的组件
- render属性:用于页面组件级别的权限管理
3、使用
步骤一:定义路由模式
- 主入口域名中定义路由模式
import React from \'react\'
import ReactDOM from \'react-dom\'
import { Provider } from \'react-redux\'
import store from \'./store\'
import {HashRouter ar Router} from \'react-router-dom\'
域名er(
<Provider store={store}>
<Router>
<App/>
</Router>
<Provider>,
域名lementById(\'root\')
)
步骤二:组件内渲染路由 + 路由声明式导航
- 导入渲染组件
- Route路由渲染组件
- 使用Link或NavLink组件完成声明式导航的定义
import React, { Component } from \'react\'
import { Route, Link } from \'react-router-dom\'
<!-- 导入渲染组件 -->
const Home = () => (<div>Home</div>)
const About = () => (<div>About</div>)
const DashBord = () => (<div>DashBord</div>)
class App extends Component {
render() {
return (
<>
<ul>
{/* 声明导航*/ }
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="{{pathname:\'/dashbord\'}}">DashBord</Link></li>
</ul>
{/*
path:可访问的url路径
component:匹配成功的渲染的组件
exact:严格匹配模式
Route组件中匹配成功,渲染会自动在域名s中添加路由导航相关属性方法
*/ }
<Route path="/" exact component={Home}></Route>
<Route path="/about" component={About}></Route>
<Route path="/dashbord" component={DashBord}></Route>
</>
);
}
}
export default App;
路由的扩展
1、路由参数
在Route定义渲染组件时给定动态绑定的参数
- params:在路由目标页面中
- 动态路由定义:
<Route path=\'/detail/:id\' component={Detail}>
- 传递:
<NavLink to=\'/detail/2\'>
- 获取:域名域名ms
- 动态路由定义:
- query:通过地址栏中的 ?key=value&key=value,
- 传递:
<NavLink to=\'/detail?name=cc\'>
- 获取:域名域名ch
- 备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
- 传递:
- state:隐式转参,用于数据的收集
- 传递:
<NavLink to=\'{{pathname:/detail?name=cc,state:{age:20}}}\'>
- 获取:域名域名e
- 作用:埋点---收集数据统计
- 传递:
2、switch组件
- 通常情况下, path和component是一一对应的关系.
- Switch可以提高路由匹配效率(单一匹配).
- 为了更好地匹配规则,轻易不要舍弃
。 - Redirect:路由从定向,一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
import { Route,Switch } from \'react-router-dom\'
<div>
<div>
<ul>
<li>
<Link to="/Guide/ContactUs">ContactUs</Link>
</li>
</ul>
</div>
<Switch>
<Route path="/Guide/ContactUs" component={ ContactUs } ></Route>
<Route path="/Guide/ContactUs" component={ ContactUs } ></Route>
<Redirect from="/" to="/public"></Redirect>
</Switch>
</div>
3、Route组件三种渲染方式
1、component
- 参数:对象
<Route path=\'/home\' component={home}/>
- 直接使用组件类--使用最多的方式
- 缺点:不能把父组件中的数据通过props传递给路由组件中
- 参数:函数
<Route path=\'/home\' component={()=><home/>} />
- 使用函数,可以写条件判断,根据条件来渲染不同的组件
- 可以通过props来完成父组件中的数据向路由渲染组件传递
- 缺点:每次匹配路由成功都会从新创建组件---效率低下,不建议使用
<Route path=\'/home\' component={()=>{
return <Home count={域名t}/>
}}/>
2、render<Route path="/home" render={props=><Home />} />
- render方式渲染,使用函数方式
- 如果匹配相同,则不重新创建,效率高
- 建议如果组件对象方式渲染(函数方式)推荐使用render
<Route path=\'/home\' render={()=>{ if(域名t==1){ return <Home1 count={域名t}/> }else{ retutn <Home2/> } }}/>
3、children
- 组件对象方式:必须匹配到path的路由规则才渲染和render与component一样
<Route path="/about" children={<About />} />
- 函数方式:不管是否和path匹配都渲染
- match为null表示当前路由规则和path不匹配,如果为对象则匹配成功
<Route path="/about" children={match=>{ if(match){ return <div>children渲染</div> } }} />
3种渲染区别总结
比较一
- component:可以使用组件类渲染或内联式方式渲染
- render:只能使用函数
- children:使用函数或直接使用组件对象
比较二
- component:内联式渲染方式在每次匹配路由成功后都将创建一个新组件
- render,children不会,所以用内联式方式建议使用后两者,内联方式渲染组件,推荐用render
比较三
- children的值是一个函数时,无论当前地址和path路径匹不匹配,都将会执行children对应的函数,当children的值为一个组件时,当前地址和path不匹配时,路由组件不渲染
- children函数方式渲染,会在形参中接受到一个对象,对象中match属性如果当前地址匹配成功返回对象,否则null
4、编程式路由导航
借助域名ory
对象上的API对操作路由跳转、前进、后退
- 域名域名()
- 域名域名ace()
- 域名域名ck()
- 域名域名rward()
- 域名域名()
注:默认组件中没有域名ory方法,需要通过withRouter高阶组件(装饰器)来进行包裹,才能得到。
域名域名(path)
或
域名域名({
pathname:\'\',
search:\'\',
state:{}
})
路由监听
在域名组件中可以添加路由监听
constructor(props) {
super(props);
域名域名en(route=>域名(route))
}
5、withRouter高阶组件
作用:把不是通过路由切换过来的组件中,将react-router 的 history、location、match 三个对象传入props对象上
- 如果在你想在一般组件使用 路由组件所特有的API 时, 就要借助 withRouter
- withRouter可以加工一般组件, 让一般组件具备路由组件所特有的API
- withRouter的返回值是一个新组件
- 引入withRouter
import { withRouter} from \'react-router-dom\'
-
执行一下withRouter
export default withRouter(Cmp)`
import React, { Component } from \'react\'
import {withRouter} from \'react-router-dom\'
class Header extends Component {
// 回退
back = () => {
域名域名ck()
}
// 前进
forward = () => {
域名域名rward()
}
/// go
go = () => {
域名域名(2)
}
render() {
// 域名(\'一般组件\',域名s)
return (
<div className="page-header">
<h2>React Router Demo</h2>
<button onClick={域名}>回退</button>
<button onClick={域名ard}>前进</button>
<button onClick={域名}>go</button>
</div>
)
}
}
export default withRouter(Header)
6、自定义路由
- 定义一个普通组件可以是类组件也可以是函数式组件
- 父组件能向子组件传值 props
- 不管路由规则是否匹配都要显示组件 Route children渲染方式(函数式)
- 注意点:react中组件是大写字母开头 html也是组件
import React from \'react\'
import {withRouter,Route} from \'react-router-dom\'
const MyLink = props=>{
const gourl=()=>{
域名(域名)
}
const Tag=域名||\'a\'
const Active=props[\'active-class\']||\'router-active-class\'
return (
<Route path={域名} children={({match})=>{
if(match){
return <Tag style={{color:\'red\'}} Onclick={gourl}>{域名dren}</Tag>
}
return <Tag onClick={gourl}>{域名dren}</Tag>
}}>
)
}
export default withRouter(MyLink)
7、多级路由
在有一些功能中,往往请求地址的前缀是相同的,不同的只是后面一部份,此时就可以使用多级路由(路由嵌套)来实现此路由的定义实现。
例: 路由规则如下
admin/index
admin/user
当前组建的请求uri地址(父组件路由uri)
let pathname=域名域名
return(
<Link to=`${pathname}/index`>用户首页</Link>
<Link to=`${pathname}/list`>用户列表</Link>
写在admin组件内,admin组件通过route来进行渲染
<Route path={`${pathname}/index`} component={main}/>
<Route path={`${pathname}/list`} component={index}/>
)
8、重定向与404
-
重定向 from从哪里来 to重定向到何处去
<Redirect from="/home" to="/" />
-
404设置
<Route component={Notfound} />
默认:匹配规则是从上项下的,一只匹配下去
switch组件:解决一直匹配问题,只要有一个符合;路由规则就停止匹配
<Switch>
<Route exact path=\'/news\' component={index}/>
<Route path=\'/news/:id\' component={Newss}/>
重定向from来源,to跳转的页面
<Redirect exact from=\'/\' to=\'/news\'>
<Route component={notFound}>
</Switch>
React Router 基本原理
React Router依赖于域名
,它是一个独立的第三方js库。可以用来兼容在不同浏览器、不同环境下对历史记录的管理,拥有统一的API。
- 老浏览器的history: 通过
hash
来存储在不同状态下的history
信息,对应createHashHistory
,通过检测域名
的值的变化,使用域名ace
方法来实现url跳转。通过注册监听window
对象上的hashChange
事件来监听路由的变化,实现历史记录的回退。 - 高版本浏览器: 利用HTML5里面的history,对应
createBrowserHistory
, 使用包括pushState
,replaceState
方法来进行跳转。通过注册监听window
对象上的popstate
事件来监听路由的变化,实现历史记录的回退。 - node环境下: 在内存中进行历史记录的存储,对应
createMemoryHistory
。直接在内存里push
和pop
状态。