React进阶组件
深入Props、组件的生命周期
1,深入Props
- 1, children属性
- 2,props校验
- 3,props校验约束规则
- 4,props的默认值
1, children属性
const App = props => {
return (
<div>{props.children}</div>
)
}
ReactDOM.render(<App>我是子节点</App>, document.getElementById('root'))
// 或者
ReactDOM.render(<App><p>我是子节点</p></App>, document.getElementById('root'))
// 或者
const Child = () => {
return (
<div>子节点</div>
)
}
const App = props => {
return (
<div>{props.children}</div>
)
}
ReactDOM.render(<App><Child/></App>, document.getElementById('root'))
// 或者
const App = props => {
return (
<div>{props.children()}</div>
)
}
ReactDOM.render(<App>{() => console.log('子节点')}</App>, document.getElementById('root'))
2,props校验
props校验允许在创建组件的时候指定props的类型、格式等。
props校验可以捕获使用组件时因为props导致的错误,给出明确的错误提示,增强组件的健壮性
使用步骤:
- 1,安装prop-types:yarn add prop-types/npm i prop-types
- 2,导入prop-types包
- 3,使用组件名.propTypes={}来给组件的props添加校验规则
import PropTypes from 'prop-types'
import React from 'react'
import ReactDOM from 'react-dom'
const App = props => {
const arr = props.colors
const lists = arr.map((item, idx) => <li key={idx}>{item}</li>)
return (
<ul>{lists}</ul>
)
}
// 添加校验规则
App.propTypes = {
colors: PropTypes.array
}
ReactDOM.render(<App colors={['red', 'yello', 'blue']}/>, document.getElementById('root'))
3,props校验约束规则
1,常见的类型:array、bool、func、number、object、string
2, 必填项:isRequired
3,特定结构的对象:shape({})
4,React元素类型:element
const App = props => {
return (
<ul></ul>
)
}
// 添加props校验
// 属性a:number
// 属性fn: 函数func并且为必填项
// 属性tag:React元素(element)
// 属性filter:对象({name: 'xiaowang', age: 18})
App.propTypes = {
a: PropTypes.number,
fn: PropTypes.func.isRequired,
tag: PropTypes.element,
filter: PropTypes.shape({
name: PropTypes.string,
age: PropTypes.number
})
}
ReactDOM.render(<App fn={() => {}}/>, document.getElementById('root'))
4,props的默认值
const App = props => {
console.log(props)
return (
<div>props的默认值:{props.pageSize}</div>
)
}
// 添加props默认值
App.defaultProps = {
pageSize: 10
}
2,组件的生命周期
生命周期的三个阶段
1,创建时(挂载阶段):执行时机 - 组件创建时(页面加载时)
-
执行顺序:钩子函数-constructor() -> 钩子函数-render() -> 钩子函数-componentDidMount
- constructor(),它的触发时机是创建组件时,最先执行,它的作用:1,初始化state 2,为事件处理程序绑定this
- render(),触发时机:每次组件渲染就会触发,作用:渲染UI,不能调用setState()
- componentDidMount(),触发时机:组件挂载(完成DOM渲染)后,作用:1,发送网络请求 2,DOM操作
2,更新阶段(更新时)
执行时机:1,setState() 2,forceUpdate() 强制更新 3,组件接收到新的props,以上三者任意一种变化,组件就会重新渲染
执行顺序:钩子函数-render() -> 钩子函数-componentDidUpdate()
- render(),触发时机:每次组件渲染都会触发,作用:渲染UI(与挂载阶段是同一个render)
- componentDidUpdate(), 触发时机:组件更新(完成DOM渲染)后,作用:1,发送网络请求 2,DOM操作,如果要setState()必须放在一个if条件中
class App extends React.Component {
state = {
count: 0
}
handleClick = () => {
this.setState({count: this.state.count += 1})
}
render() {
return (
<div>
<Child count={this.state.count}/>
<button onClick={this.handleClick}>更新数据</button>
</div>
)
}
}
class Child extends React.Component {
render() {
return (
<h1 id="title">数值变化: {this.props.count}</h1>
)
}
// 如果要调用setState()更新状态,必须放在if条件中
componentDidUpdate(prevProps) {
// 获取DOM
const title = document.getElementById('title')
// this.setState({}) // 会导致递归更新,分析:当触发handleClick事件,会触发setState,触发setState,<Child count={this.state.count}/>就会更新,子组件更新
// 就会触发子组件的render()方法,走完后会触发componentDidUpdate(),而在componentDidUpdate()方法里又调用setState(),所以就会导致递归更新。
// 所以一般把this.setState({})放在if条件里
// if语句一般是:比较更新前后的props是否相同,来决定是否重新渲染组件
// prevProps:上一次的props
// 当前的props: this.props
if (prevProps !== this.props) {
this.setState({})
}
}
}
3,卸载时(卸载阶段)
执行时机:组件从页面消失
钩子函数是componentWillUnmount(),触发时机:组件卸载(从页面中消失),作用:执行清理工作(比如:清楚定时器)
class App extends React.Component {
state = {
count: 0
}
handleClick = () => {
this.setState({count: this.state.count += 1})
}
render() {
return (
<div>
{
this.state.count > 3 ? (<h1>暂停数值更新</h1>) : (<Child count={this.state.count}/>)
}
<button onClick={this.handleClick}>更新数据</button>
</div>
)
}
}
class Child extends React.Component {
// 开启一个定时器
componentDidMount() {
this.timerId = setInterval(() =>{console.log('定时器')}, 1000)
}
render() {
return (
<h1 id="title">数值变化: {this.props.count}</h1>
)
}
// 如果要调用setState()更新状态,必须放在if条件中
componentDidUpdate(prevProps) {
// 获取DOM
const title = document.getElementById('title')
// this.setState({}) // 会导致递归更新,分析:当触发handleClick事件,会触发setState,触发setState,<Child count={this.state.count}/>就会更新,子组件更新
// 就会触发子组件的render()方法,走完后会触发componentDidUpdate(),而在componentDidUpdate()方法里又调用setState(),所以就会导致递归更新。
// 所以一般把this.setState({})放在if条件里
// if语句一般是:比较更新前后的props是否相同,来决定是否重新渲染组件
// prevProps:上一次的props
// 当前的props: this.props
if (prevProps !== this.props) {
this.setState({})
}
}
componentWillUnmount() {
console.log('componentWillUnmount')
clearInterval(this.timerId) // 清除定时器
}
}
react生命周期图








网友评论