Front-end/react/6.组件生命周期.md

269 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

只有类组件才有生命周期
1. 创建
```html
class LifeCreate extends React.Component{
constructor(props){
super(props)
console.warn('1.生命周期钩子函数constructor')
}
componentDidMount(){
console.warn('3.生命周期钩子函数componentDidMount')
}
render(){
console.warn('2.生命周期钩子函数render')
return (<div><h3>hello</h3></div>)
}
}
```
2. 更新
New props,setState,forceUpdate
```html
class LifeUpdate extends React.Component{
constructor(props){
super(props)
console.warn('1.生命周期钩子函数constructor')
this.state = {
count:0
}
}
componentDidMount(){
console.log(document.getElementById('root'))
console.warn('3.生命周期钩子函数componentDidMount')
}
handlerClick= ()=>{
// this.setState({
// count:this.state.count+1
// })
this.forceUpdate()
}
render(){
console.warn('2.生命周期钩子函数render')
return (<div><Counter count = {this.state.count}/><button onClick={this.handlerClick}>hello</button></div>)
}
}
class Counter extends React.Component{
componentDidUpdate(prevProps){
console.warn('---------------生命周期钩子函数componentDidUpdate')
if(prevProps.count!=this.props.count){
this.setState({})
}
}
render(){
console.warn('---------------生命周期钩子函数render')
return (<p>点击次数{this.props.count}</p>)
}
}
```
3. 卸载
```html
class LifeEnd extends React.Component{
constructor(props){
super(props)
console.warn('1.生命周期钩子函数constructor')
this.state = {
count:0
}
}
componentDidMount(){
console.log(document.getElementById('root'))
console.warn('3.生命周期钩子函数componentDidMount')
}
handlerClick= ()=>{
this.setState({
count:this.state.count+1
})
// this.forceUpdate()
}
render(){
console.warn('2.生命周期钩子函数render')
return (<div>
{this.state.count>3?("goodby"):<Counter count = {this.state.count}/>}
<button onClick={this.handlerClick}>hello</button></div>)
}
}
class Counter extends React.Component{
componentDidUpdate(prevProps){
console.warn('---------------生命周期钩子函数componentDidUpdate')
if(prevProps.count!==this.props.count){
this.setState({})
}
}
componentDidMount(){
this.timerId = setInterval(()=>{
console.log("定时器在执行")
},500)
}
componentWillUnmount(){
clearInterval(this.timerId)
console.warn("结束")
}
render(){
console.warn('---------------生命周期钩子函数render')
return (<p>点击次数{this.props.count}</p>)
}
}
```
# 组件复用
复用组件的状态逻辑1.state2.操作state的方法.
## render props
将要复用的state和操作state的方法封装到一个组件中
添加一个值为函数的prop,通过函数参数来获取(需要组件内部来实现)
使用该函数的返回值,作为要渲染的UI内容
```html
import img from './img/20200205205324.jpg'
import PropTypes from "prop-types"
class RepeatUse extends React.Component {
render(){
return (
<div>
<h1>render props 复用模式</h1>
<Mouse >{mouse=>{return (<p>X:{mouse.x},Y{mouse.y}</p>)}}</Mouse>
<Mouse >{mouse=>{return <img src={img} alt="" style={{position:'absolute',top:mouse.y-350,left:mouse.x-350}} />}}</Mouse>
</div>
)
}
}
class Mouse extends React.Component {
state = {
x: 0, y: 0
}
handleMouseMove = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
// 监听鼠标移动
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove)
}
componentWillUnmount(){
window.removeEventListener('mousemove', this.handleMouseMove)
}
render(){
return this.props.children(this.state)
}
}
Mouse.propTypes={
children:PropTypes.func.isRequired
}
```
## 高阶组件HOC
是一个函数,接收要包装的组件,返回增强后的组件
1. 创建函数以with开头
2. 指定函数参数,参数大写开头
3. 函数内部创建类组件,提供复用状态逻辑代码
4. 在组件中渲染参数组件,同时通过prop传递给参数组件(high order component)
5. 调用高阶组件,传入要增强的组件,通过返回值拿到增强后的组件并将其渲染到页面.
```html
class RepeatUse extends React.Component {
render(){
return (
<div>
<h1>render props 复用模式</h1>
<MoousePosition ></MoousePosition>
</div>
)
}
}
function withMouse(WrappedComponent){
class Mouse extends React.Component {
state = {
x: 0, y: 0
}
handleMouseMove = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
// 监听鼠标移动
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove)
}
componentWillUnmount(){
window.removeEventListener('mousemove', this.handleMouseMove)
}
render(){
// return this.props.children(this.state)
return <WrappedComponent {...this.state}></WrappedComponent>
}
}
return Mouse
}
const Position = props=>(
<p>
鼠标当前位置(x:{props.x},y:{props.y})
</p>
)
const MoousePosition = withMouse(Position)
```
### 设置displayName便于区分
```html
class RepeatUse extends React.Component {
render(){
return (
<div>
<h1>render props 复用模式</h1>
<MoousePosition ></MoousePosition>
{/* <MoousePosition >{mouse=>{return (<p>X:{mouse.x},Y{mouse.y}</p>)}}</MoousePosition> */}
{/* <MoousePosition >{mouse=>{return <img src={img} alt="" style={{position:'absolute',top:mouse.y-350,left:mouse.x-350}} />}}</MoousePosition> */}
</div>
)
}
}
function getDisplayName(WrappedComponent){
return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}
function withMouse(WrappedComponent){
class Mouse extends React.Component {
state = {
x: 0, y: 0
}
handleMouseMove = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
// 监听鼠标移动,仅挂载执行一次
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove)
}
componentWillUnmount(){
window.removeEventListener('mousemove', this.handleMouseMove)
}
render(){
// return this.props.children(this.state)
return <WrappedComponent {...this.state}></WrappedComponent>
}
}
// 设置展示名称
Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`
return Mouse
}
const Position = props=>(
<p>
鼠标当前位置(x:{props.x},y:{props.y})
</p>
)
const MoousePosition = withMouse(Position)
```
## 高阶组件传递 props
```html
render(){
// return this.props.children(this.state)
return <WrappedComponent {...this.state}{...this.props}></WrappedComponent>
}
```
## 组件极简模型
(state,props)=>UI