- react的组件树结构
根组件
- 路由组件
- 展示组件
- 链接组件
- 链接组件
- 路由规则
- / 重定向(首页)
- 路由规则
- /page1 父组件1(和路径绑定的页面1)
- 子组件1(计时器1)
- 子组件2(计时器2)
- 路由规则
- /page2 父组件2(和路径绑定的页面2)
- 高阶组件(计时器逻辑)
- 原始组件3(计时器ui3)
- 高阶组件(计时器逻辑)
- 原始组件4(计时器ui4)
- 子组件的定义和调用
1.定义计时器1
export default function Timer1(){
const [time,setTime]=useState(0)
useEffect(()=>{
const interval=setInterval(()=>{
setTime(preTime=>preTime+1)
},1000)
return ()=>{
clearInterval(interval)
}
},[])
return(
<div>计时器1:{time}秒</div>
)
}
2.定义计时器2
export default function Timer2(){
const [time,setTime]=useState(0)
useEffect(()=>{
const interval=setInterval(()=>{
setTime(preTime=>preTime+1)
},1000)
return ()=>{
clearInterval(interval)
}
},[])
return(
<div>计时器2:{time}秒</div>
)
}
3.调用两个计时器
export default function Page1(){
return (
<div>
<Timer1/>
<Timer2/>
</div>
)
}
优化:复用整个函数组件
//将ui不同的部分作为父子组件的参数,这样可以复用子组件的逻辑
1.定义计时器
export default function Timer(props){
const [time,setTime]=useState(0)
useEffect(()=>{
const interval=setInterval(()=>{
setTime(preTime=>preTime+1)
},1000)
return ()=>{
clearInterval(interval)
}
},[])
return(
<div>{props.name}:{time}秒</div>
)
}
2.调用计时器
export default function Page1(){
return (
<div>
<Timer name={"计时器1"}/>
<Timer name={"计时器2"}/>
</div>
)
}
- 复用类组件逻辑:高阶组件的定义和调用
1.定义原始组件:定时器ui1和定时器ui2
export class TimerUI1 extends Component{
render(){
return(
<div>计时器1:{this.props.time}秒</div>
)
}
}
export class TimerUI2 extends Component{
render(){
return(
<div>计时器2:{this.props.time}秒</div>
)
}
}
2.定义高阶组件:定时器逻辑
export default function withTimerLogic(TimerUI){
return class TimerLogic extends Component{
state={
time:0
}
interval=null
//在类组件里声明的是属性,所以不需要写let或者const
//在类组件外或者函数组件里或者render方法里声明的是变量,所以需要写let或者const
componentDidMount(){
this.interval=setInterval(()=>{
this.setState(prevState=>({time:prevState.time+1}))
},1000)
}
componentWillUnmount(){
clearInterval(this.interval)
}
render(){
return(
<TimerUI time={this.state.time} {...this.props}/>
//爷:Page2,父:TimeLogic,子:TimerUI
//time是父亲创造,传递给孩子。props是爷爷传递给父亲传递给孩子
)
}
}
}
3.调用增强组件:定时器
const Timer1=withTimerLogic(TimerUI1)
const Timer2=withTimerLogic(TimerUI2)
export default class Page2 extends Component{
render(){
return(
<div>
<Timer1/>
<Timer2/>
</div>
)
}
}
优化:进一步复用类组件ui
1.定义原始组件:定时器ui
export class TimerUI extends Component{
render(){
return(
<div>{this.props.name}:{this.props.time}秒</div>
)
}
}
2.定义高阶组件:定时器逻辑
export default function withTimerLogic(TimerUI){
return class TimerLogic extends Component{
state={
time:0
}
interval=null
//在类组件里声明的是属性,所以不需要写let或者const
//在类组件外或者函数组件里或者render方法里声明的是变量,所以需要写let或者const
componentDidMount(){
this.interval=setInterval(()=>{
this.setState(prevState=>({time:prevState.time+1}))
},1000)
}
componentWillUnmount(){
clearInterval(this.interval)
}
render(){
return(
<TimerUI time={this.state.time} {...this.props}/>
//爷:Page2,父:TimeLogic,子:TimerUI
//time是父亲创造,传递给孩子。props是爷爷传递给父亲传递给孩子
)
}
}
}
3.调用增强组件:定时器
const Timer=withTimerLogic(TimerUI)
export default class Page2 extends Component{
render(){
return(
<div>
<Timer name={"计时器1"}/>
<Timer name={"计时器2"}/>
</div>
)
}
}
- 配置路由规则
- App.js
import React,{Component} from 'react'
import {BrowserRouter as Router,Link,Switch,Route} from 'react-router-dom'
import {Layout,Menu} from 'antd'
import Home from './Home'
import Page1 from './Page1'
import Page2 from './Page2'
const {Header,Content}=Layout
export default class App extends Component{
render(){
return(
<Router>
<Layout>
<Header>
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={["1"]}>
<Menu.Item key="1">
<Link to="/">首页</Link>
</Menu.Item>
<Menu.Item key="2">
<Link to="/page1">页面1</Link>
</Menu.Item>
<Menu.Item key="3">
<Link to="/page2">页面2</Link>
</Menu.Item>
</Menu>
</Header>
<Content>
<Switch>
<Route path="/" component={Home} exact />
//如果不加exact,点击页面1和页面2也都会跳转到首页
<Route path="/page1" component={Page1} />
<Route path="/page2" component={Page2} />
</Switch>
</Content>
</Layout>
</Router>
)
}
}
- Home.js
import React from 'react'
import {Layout} from 'antd'
const {Content}=Layout
export default Home extends Component{
render(){
return(
<Content>这是首页</Content>
)
}
}