高阶组件HOC
react中复用组件的一种姿势,基于react特性组成的一种模式
高阶组件是:参数为组件,返回值为新组件并赋予更多功能的一个函数
自定义一个随机换色高阶组件:
const Rainbow = (WrappedComponent)=>{
const colors =['red','blue','green','orange','yellow','pink']
const randomColors = colors[Math.floor(Math.random()*6)]
const className = randomcolors + '-text'
return (props) => (
<div className={className}>
<WrappedComponent {...props}>
</div>
)
export default Rainbow
import Rainbow from '../hc/Rainbow'
const Home =()=>{
...定义Home函数组件
}
export default Rainbow(Home) //当做函数一样调用高阶组件
Home页面每刷新一次,颜色就随机生成一次
React Router
Router有两种模式:History和Hash模式
- 如果没有后台服务器,就用Hash模式
- 如果有后台服务器,配置所有路径都到首页才能使用History模式(开了server就算有后台服务器)
Hash模式可以乱用,因为只是Hash值,History模式不可以乱用,需要匹配到后台设定了的路径
class App extends Component{
render(){
return (
<BrowserRouter>
<Navbar/> //只控制Nav的UI展示,实际控制路由跳转渲染的是下面三个Route
<Route path='/' component ={Home}/>
<Route path='/about' component ={About}/>
<Route path='/contact' component ={Contact}/> //子组件可以拿到路由信息
</BrowserRouter>
)
}
}
Router路由对象的三个属性
首先明确:
在父组件中 各子组件 若是通过路由进行切换渲染展示的,那么子组件可以通过props拿到父组件传来的路由对象的三个对象属性
- history:可以追踪页面的跳转记录,里面包含各种方法
- location:当前页面的位置信息,如pathname
- match:设置路由参数的时候常使用该对象属性,如params
再者注意:
Navbar组件只是负责Nav导航的UI渲染展示,没有路由信息,只有各跳转子组件Route才有路由对象信息,即只要使用了路由来控制的组件,会自动继承路由给我们提供的一些对象
问题:如何才能让没有拥有路由对象信息的Navbar组件拥有 路由对象信息?针对不是路由来控制的 页面跳转
解决:使用高阶组件withRouterexport default withRouter(Navbar)
重定向
方法一:使用钩子:history对象属性的push方法(编程式的重定向)props.history.push('/about')
方法二:V6中,使用新增的
<Routes>
<Route path="/home" element={<Home/>} />
<Route path="/" element={<Navigate to="/home"/>}>
<Route path="about" render={() => <Redirect to="about-us" />}
</Routes>
React+axios
JSONPlaceholder 第三方接口,可提供一些用于测试的虚拟数据
请求接口需要在react的哪个生命周期中发起请求?→ 第一阶段完成挂载后请求第三方提供的数据(componentDidMount)
react生命周期大致分为:挂载阶段、更新阶段、卸载阶段
在挂载阶段:先创建constructor进行数据初始化 → 第一次渲染,调用render方法 → 执行对应的数据,进行状态更新
业务一:点击不同Tab跳转到不同post内容页面
- 使用Router,在路由文件添加路由跳转信息
<Route path='/:post_id' component={Post}/>
- 点击不同Tab,获取其路由参数进行保存,根据获取的URL参数去请求获取对应的数据,并进行渲染展示,
创建单个Post文件,作为展示博客内容的页面 获取url路由参数:在DOM渲染的时候即componentDidMount钩子中:拿到路由对象的match对象属性 中的 params,创建变量存储params 每篇博客Tab绑定对应的链接在其title上,以便点击跳转,通过Link链接跳转,获取每个Post的id 当保存了params路由参数后,就可以拿着参数去发起axios请求
具体步骤示例如下:
//链接跳转、在父布局路由中添加一个出口
render(){
const {posts} = this.state
const postList = posts.length ? (posts.map(post => {
return (
<div className='post card' key ={post.id}>
<Link to={'/'+post.id}>
<span className='card-title'>{post.title}</span>
</Link>
<p>{post.body}</p>
</div>
)
})) : ()
}
//获取路由参数、发起axios请求
class Post extends Component{
state ={
post:null
}
componentDidMount(){
let id = this.props.match.params.post_id
axios.get('https://jsonplaceholder.typicode.com/posts'/ + id)
.then(res => { this.setState({ post:res.data } )})
}
render(){
const post = this.state.post ? (
<div className='post'>
<h4>{th is.state.post.title}</h4>
<p>{this.state.post.body}</p>
</div>
) : (
<div className='container'>博客正在加载中...</div>
)
return (
<div className='container'>
{this.state.post}
</div>
)
}
}
Switch组件
作用:只渲染第一个匹配到的路由组件、重定向组件
V6升级为Routes组件
用法:包裹住所有Route组件即可