什么是路由
简单的说就是根据不同的地址,web服务器处理不同的业务以及逻辑。
以下代码全部运行在react脚手架中
纯组件的基本使用
// 组件更新机制:
// 只要父组件重新渲染了, 所有的组件子树, 也会更新
// 性能优化
// 1. 减轻state
// 2. 避免不必要的重新渲染 (性能优化)
// shouldComponentUpdate(nextProps, nextState) { .... }
// 钩子函数返回一个布尔值, true要更新 false不更新
// 手动实现固然是可以的, 但是太麻烦
// 3. 实际官网提供了一个纯组件, 内部已经帮你实现好了 shouldComponentUpdate 的逻辑
// 会帮你进行props 和 state的比对, 决定是否要更新
// 普通组件: class App extends React.Component
// 纯组件: class App extends React.PureComponent 会比普通组件, 多一个比对数据的过程
// 比如: 一个组件要渲染出来, 性能损耗很大, 此时可以考虑纯组件, 避免掉一些无意义的更新
// 不是所有的场景, 都要用纯组件, 正常应该都用普通组件
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.PureComponent {
state = {
nameList: ['帅鹏', '吕布', '张飞'],
currentName: '',
}
render() {
console.log('App-render')
return (
<div>
<h1>我是App组件</h1>
<h3>结果: {this.state.currentName}</h3>
<button onClick={this.handleClick.bind(this)}>点名</button>
</div>
)
}
handleClick() {
const randomIndex = parseInt(Math.random() * this.state.nameList.length)
const currentName = this.state.nameList[randomIndex]
this.setState({
currentName,
})
console.log(currentName)
}
// 需求: 如果state的值, 没有发生变化, 其实也不需要更新, 避免一些不必要的更新
// shouldComponentUpdate(nextProps, nextState) {
// if (this.state.currentName === nextState.currentName) {
// return false
// } else {
// return true
// }
// }
}
ReactDOM.render(<App></App>, document.getElementById('root'))
纯组件使用的注意点
// 4. 纯组件的使用注意点 (如果纯组件有子组件, 子组件也要是纯组件 (一家子都纯))
// (1) 纯组件内部进行的是浅层对比, 值类型没有问题, 复杂类型只比较地址
// (2) 使用纯组件, 更新数据时, 简单类型没有问题, 复杂类型更新了, 是需要修改地址的(新对象 / 新数组)
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.PureComponent {
state = {
nameList: ['帅鹏', '吕布', '张飞'],
currentName: '',
obj: {
name: 'zs',
age: 18,
},
}
render() {
console.log('App-render')
return (
<div>
<h1>我是App组件</h1>
<p>name: {this.state.obj.name}</p>
<p>{this.state.nameList}</p>
<button onClick={this.handleClick.bind(this)}>改值</button>
</div>
)
}
handleClick() {
// 要更新对象, 要准备一个新对象
// const obj = { ...this.state.obj }
// obj.name = 'ls'
// this.setState({
// obj: obj,
// })
// 要更新数组, 要准备一个新数组
// this.setState({
// nameList: [...this.state.nameList, '王五'],
// })
const arr = [...this.state.nameList]
arr.push('王五')
this.setState({
nameList: arr,
})
}
}
ReactDOM.render(<App></App>, document.getElementById('root'))
路由的基本初体验
import React from 'react'
import ReactDOM from 'react-dom'
import { HashRouter, Link, Route } from 'react-router-dom'
// 路由的使用:
// 1. 下载 yarn add react-router-dom
// 2. react-router-dom是一个包, 包含了很多的组件
// 3. HashRouter组件, 是整个的路由对象, 一个项目就一个, 需要将整个项目的内容包裹
// 4. Link组件, 渲染成一个 a 链接, 可以用于路由跳转, 通过 to 配置路径
// 5. Route组件, 配置路由规则(哪个路径匹配哪个组件), 也是路由出口!
// 每个Route互相之间是独立的, 只要路径匹配, 就可以展示配置的组件
// 定义了三个函数组件
const Home = () => <div>我是Home组件</div>
const Login = () => <div>我是Login组件</div>
const User = () => <div>我是User组件</div>
class App extends React.PureComponent {
render() {
return (
<div>
<h1>我是App组件</h1>
<ul>
<li>
<Link to="/home">首页</Link>
</li>
<li>
<Link to="/login">登录</Link>
</li>
<li>
<Link to="/user">用户</Link>
</li>
</ul>
{/* 只要path路径, 和地址栏的路径匹配, 就会展示配置的组件 */}
<Route path="/home" component={Home}></Route>
<Route path="/login" component={Login}></Route>
<Route path="/user" component={User}></Route>
</div>
)
}
}
ReactDOM.render(
<HashRouter>
<App></App>
</HashRouter>,
document.getElementById('root')
)
HashRouter和BrowserRouter
import React from 'react'
import ReactDOM from 'react-dom'
import { HashRouter as Router, Link, Route } from 'react-router-dom'
// Router组件, 有两种 HashRouter, BrowserRouter
// 1. HashRouter底层实现基于: 地址栏的hash值, 基于锚点跳转实现的
// 2. BrowserRouter底层实现基于: h5 的 history API, 地址栏没有 #
// (如果要用开发时, 没有问题, 但是上线了, 是需要后台配置的)
// 定义了三个函数组件
const Home = () => <div>我是Home组件</div>
const Login = () => <div>我是Login组件</div>
const User = () => <div>我是User组件</div>
class App extends React.PureComponent {
render() {
return (
<div>
<h1>我是App组件</h1>
<ul>
<li>
<Link to="/home">首页</Link>
</li>
<li>
<Link to="/login">登录</Link>
</li>
<li>
<Link to="/user">用户</Link>
</li>
</ul>
{/* 只要path路径, 和地址栏的路径匹配, 就会展示配置的组件 */}
<Route path="/home" component={Home}></Route>
<Route path="/login" component={Login}></Route>
<Route path="/user" component={User}></Route>
</div>
)
}
}
ReactDOM.render(
<Router>
<App></App>
</Router>,
document.getElementById('root')
)
Link组件和NavLink组件
import React from 'react'
import ReactDOM from 'react-dom'
import { HashRouter as Router, NavLink, Route } from 'react-router-dom'
import './index.css'
// Link组件 和 NavLink组件
// 1. Link组件, 渲染成a链接, 用于路由跳转, 通过to配置路径
// 默认的Link, 不会有高亮的类名标识
// 2. NavLink组件, 渲染成a链接, 用于路由跳转, 通过to配置路径
// (1) NavLink, 在路径匹配时, 会有高亮的类名 active
// (2) 可以通过activeClassName, 配置高亮的类名
// (3) 可以通过activeStyle, 直接配置改标签, 高亮的样式
// (4) 进行的是模糊匹配 to="/home" 可以匹配 /home /home/aa
// 精确匹配, 需要配置 exact 属性, to="/home", 只能匹配 /home, 只会在 /home 时高亮
// 定义了三个函数组件
const Home = () => <div>我是Home组件</div>
const Login = () => <div>我是Login组件</div>
const User = () => <div>我是User组件</div>
class App extends React.PureComponent {
render() {
return (
<div>
<h1>我是App组件</h1>
<ul>
<li>
<NavLink
exact
to="/"
activeStyle={{ color: 'red', fontSize: '30px' }}
>
首页
</NavLink>
</li>
<li>
<NavLink to="/login" activeClassName="selected">
登录
</NavLink>
</li>
<li>
<NavLink to="/user" activeClassName="selected">
用户
</NavLink>
</li>
</ul>
{/* 只要path路径, 和地址栏的路径匹配, 就会展示配置的组件 */}
<Route path="/home" component={Home}></Route>
<Route path="/login" component={Login}></Route>
<Route path="/user" component={User}></Route>
</div>
)
}
}
ReactDOM.render(
<Router>
<App></App>
</Router>,
document.getElementById('root')
)
/**index.css*/
.active {
color: red;
font-size: 30px;
}
.selected {
color: blue;
font-size: 30px;
}
Route和Switch组件
import React from 'react'
import ReactDOM from 'react-dom'
import { HashRouter as Router, NavLink, Route, Switch } from 'react-router-dom'
import './index.css'
// Route组件
// 作用: 可以配置路由规则, 也是路由的出口, 只要路径匹配了, 那么配置的组件, 就会在这里展示
// <Route path="/login" component={Login}></Route>
// 1. 每个Route之间, 互相是独立的 (包括配置多个相同路径, 显示不同组件, 也是可以的)
// 2. Route配置的路径, 也是进行的模糊匹配, 可以通过 exact 进行精确匹配
// 3. 如果不配置路径, 那么配置的组件, 默认都会展示
// 会配合Switch组件, 可以完成404页面的配置
// Switch组件: 可以将多个Route组件包裹, 可以让第一个匹配的Route组件展示, 后续的不管
// 定义了函数组件
const Home = () => <div>我是Home组件</div>
const Login = () => <div>我是Login组件</div>
const User = () => <div>我是User组件</div>
const Error = () => <div>我是404页面, 您要访问的页面不存在!!!</div>
class App extends React.PureComponent {
render() {
return (
<div>
<h1>我是App组件</h1>
<ul>
<li>
<NavLink
exact
to="/"
activeStyle={{ color: 'red', fontSize: '30px' }}
>
首页
</NavLink>
</li>
<li>
<NavLink to="/login" activeClassName="selected">
登录
</NavLink>
</li>
<li>
<NavLink to="/user" activeClassName="selected">
用户
</NavLink>
</li>
</ul>
{/* 只要path路径, 和地址栏的路径匹配, 就会展示配置的组件 */}
<Switch>
<Route path="/" component={Home} exact></Route>
<Route path="/login" component={Login}></Route>
<Route path="/user" component={User}></Route>
<Route component={Error}></Route>
</Switch>
</div>
)
}
}
ReactDOM.render(
<Router>
<App></App>
</Router>,
document.getElementById('root')
)
嵌套路由
import React from 'react'
import ReactDOM from 'react-dom'
import {
HashRouter as Router,
NavLink,
Route,
Switch,
Redirect,
} from 'react-router-dom'
import './index.css'
// Redirect组件: 可以重定向, from从哪 to跳到哪
// react中, 配置嵌套路由, 非常的简单, 你只需要在需要写嵌套子路由的地方, 直接写Route组件即可
// 前提条件, 你配置的嵌套子路由, 路径一定要包含父路由的路径
// 定义了函数组件
const Home = () => (
<div>
<h3>我是Home组件</h3>
</div>
)
const Login = () => (
<div>
<h3>我是Login组件</h3>
</div>
)
// ------------------------------------------------------------------------
// 需求: 用户User组件内部, 还有个人信息, 我的收藏
const User = () => (
<div>
<h3>我是User组件</h3>
<Route path="/user" exact component={UserDefault}></Route>
<Route path="/user/info" component={Info}></Route>
<Route path="/user/star" component={Star}></Route>
</div>
)
const UserDefault = () => <div>我是默认的User内容</div>
const Info = () => <div>我是Info组件</div>
const Star = () => <div>我是Star组件</div>
// -------------------------------------------------------------------------
const Error = () => <div>我是404页面, 您要访问的页面不存在!!!</div>
class App extends React.PureComponent {
render() {
return (
<div>
<h1>我是App组件</h1>
<ul>
<li>
<NavLink
exact
to="/"
activeStyle={{ color: 'red', fontSize: '30px' }}
>
首页
</NavLink>
</li>
<li>
<NavLink to="/login" activeClassName="selected">
登录
</NavLink>
</li>
<li>
<NavLink to="/user" activeClassName="selected">
用户
</NavLink>
</li>
</ul>
{/* 只要path路径, 和地址栏的路径匹配, 就会展示配置的组件 */}
<Switch>
<Route path="/" component={Home} exact></Route>
<Redirect from="/home" to="/"></Redirect>
<Route path="/login" component={Login}></Route>
<Route path="/user" component={User}></Route>
<Route component={Error}></Route>
</Switch>
</div>
)
}
}
ReactDOM.render(
<Router>
<App></App>
</Router>,
document.getElementById('root')
)
路由传参
import React from 'react'
import ReactDOM from 'react-dom'
import { HashRouter as Router, Route, Link } from 'react-router-dom'
import './index.css'
// 如果想拿到动态路由的参数信息, 需要通过props获取,
// Route会将路由相关信息, 相关方法, 都会通过 props 传给你的组件
// const Product = (props) => <div>我是product组件</div>
class Product extends React.Component {
render() {
// this.props 参数
// (1) history 里面存放的是跳转路由的方法
// (2) location 里面存放的是当前路由地址
// (3) match 里面存放的是动态路由参数
console.log(this.props)
console.log(this.props.match.params.id)
return (
<div>
<h3>我是product组件 - {this.props.match.params.id}</h3>
<button onClick={this.handleClick.bind(this)}>回首页</button>
</div>
)
}
handleClick() {
// console.log(this.props.history)
// this.props.history.go(-1)
this.props.history.push('/home')
}
}
const Home = () => <div>我是首页</div>
class App extends React.Component {
render() {
return (
<div>
<h1>我是App组件</h1>
<div>
<Link to="/home">首页</Link>
<Link to="/product/1">商品1</Link>
<Link to="/product/2">商品2</Link>
<Link to="/product/3">商品3</Link>
<Link to="/product/4">商品4</Link>
</div>
<Route path="/product/:id" component={Product}></Route>
<Route path="/home" component={Home}></Route>
</div>
)
}
}
ReactDOM.render(
<Router>
<App></App>
</Router>,
document.getElementById('root')
)
到此这篇关于五分钟教你了解一下react路由知识的文章就介绍到这了,更多相关react路由内容请搜索极客世界以前的文章或继续浏览下面的相关文章希望大家以后多多支持极客世界! |
请发表评论