在react中state中存放的是数据
初次渲染时react会根据state(model),创建出一个虚拟DOM树
然后经过render将虚拟DOM形成出真实的DOM
当数据发生变化的时候(setState())他会生成一个新的虚拟DOM树
通过deff算法计算上一次的值和新更新的值有什么新的变化
最后render只会将更新的内容渲染到真实DOM上
安装
安装react-router-dom
yarn add react-router-dom --save
代码中基本使用
import React,{ Component } from "react";
import { BrowserRouter,Route,Switch } from "react-router-dom";
import routers from "./router/index";
class App extends Component<any,any>{
render(): React.ReactNode {
return (
<BrowserRouter>
{
routers.map(router=>{
return (
<Route
path={router.path}
component = { router.component }
></Route>
)
})
}
</BrowserRouter>
)
}
}
export default App
1.写法不同:
一般组件:<Demo/>
路由组件:<Route path="/demo" component={Demo}/>
2.存放位置不同:
一般组件:components
路由组件:pages
3.接收到的props不同:
一般组件:写组件标签时传递了什么,就能收到什么
路由组件:接收到三个固定的属性
history:
go: ƒ go(n)
goBack: ƒ goBack()
goForward: ƒ goForward()
push: ƒ push(path, state)
replace: ƒ replace(path, state)
location:
pathname: "/about"
search: ""
state: undefined
match:
params: {}
path: "/about"
url: "/about"
路由传参接受
方式1
通过params
<Route path='/:userId' component={User}></Route>
跳转路由
this.props.history.push('/1234')
接收
this.props.match.params.userId
特点 :刷新页面数据不会丢失,但是只能传字符串
方式2 通过query
跳转路由
this.props.history.push({ pathname: '/home' , query : { id: '6666' }})
接收参数
this.props.location.query.id
方式3 通过state
跳转路由
this.props.history.push({ pathname: '/home' , state: { id: '6666' }})
接收参数
this.props.location.state.id
通过params传参 页面刷新 数据不会丢失 query与state传参 刷新页面数据会丢失
嵌套路由
先定义页面
Topic.js, About.js, Topic.js, A.js, B.js (将里面的文字做相应的替换)
import React from 'react'
export default class Topic extends React.Component {
render() {
return (
<>
<div>
Topic页面
</div>
</>
)
}
}
Home2.js
import React from 'react'
import { Link } from 'react-router-dom'
export default class Home extends React.Component {
render() {
return (
<div>
<ul>
<li>
<Link to="/">Home2</Link>
</li>
<li>
<Link to="/about">About2</Link>
</li>
<li>
<Link to="/topic">Topics2</Link>
</li>
</ul>
<hr/>
{/* 子页面 */}
{/* 所有子组件 */}
{this.props.children}
</div>
)
}
}
router.js
import React from 'react'
import { HashRouter as Router, Route, Link, Switch, useRouteMatch, useParams } from 'react-router-dom'
import Main from './Main'
import About from './About'
import Topic from './Topic'
import Home from './Home'
import A from './A'
import B from './B'
/**
* 这个页面就是 最终输出页面
* 在项目根目录的 index.js 文件里面
*
* import Router from './pages/router_demo/router02/router';
* ReactDOM.render(<Router />, document.getElementById('root'));
*/
export default class IRouter extends React.Component {
render() {
return (
<>
<Router>
{/* 只能有一个根节点 */}
<Home>
{/* 页面路由,一个 Route 代表一个页面 */}
{/* 4.0 版本开始允许加载多个路由,所以建议加上 exact 进行精准匹配*/}
<Route exact={true} path="/" component={Main}/>
<Route exact={true} path="/about" component={About}/>
<Route exact={true} path="/topic" component={Topic}/>
{/* 嵌套路由,不能在父级家 exact,因为先要匹配父级然后才能匹配子集 */}
{/* 比如:/nested/a , 会先匹配父级 /nested 饭后才能匹配 /nested/a */}
<Route path="/nested" component={() => <Nested />} />
</Home>
</Router>
</>
)
}
}
/**
* 函数组件
* @param {*} props
*/
export function Nested(props) {
// 获取route的匹配数据
// path 路径, url 路径, params 参数
const { path, url, params } = useRouteMatch()
// 获取 path 参数, http://localhost:3000/a/:number
// const { number } = useParams()
console.log(path, url, params)
return (
<>
<ul>
<li>
<Link to={`${path}/a`}>A页面</Link>
</li>
<li>
<Link to={`${path}/b`}>B页面</Link>
</li>
</ul>
<hr/>
{/* {props.children} */}
<Switch>
<Route exact path={path} component={() => <h3>嵌套路由</h3>}/>
<Route path={`${path}/a`} component={A}/>
<Route path={`${path}/b`} component={B}/>
</Switch>
</>
)
}
嵌套路由的重点在于,嵌套路由,不能在父级加 exact(精准匹配),因为先要匹配 父级 然后才能匹配 子集
比如:/nested/a , 会先匹配父级 /nested 后才能匹配 /nested/a
<Route path="/nested" component={() => <Nested />} />
....... 分隔符 ...........
// <Nested /> 组件的内部
// 这里的 path 就是 /nested
// `${path}/a` 就是 /nested/a
<Switch>
<Route exact path={path} component={() => <h3>嵌套路由</h3>}/>
<Route path={`${path}/a`} component={A}/>
<Route path={`${path}/b`} component={B}/>
</Switch>