生命周期函数
1.如果不初始化state或不进行方法绑定,则不需要React组件实现构造函数
2.constructor:通过this.state赋值对象来初始化内部的state 为事件绑定this
组件之间的通信
父组件通过属性=值的形式来传递给子组件数据
子组件通过props参数获取父组件传递过来的数据
开发中不能直接通过修改state的值来让界面发生更新
React并没有实现类似Vue的监听数据变化,必须通过setState来告知react数据已经发生变化
setState异步更新
changeText() {
this.setState({
message: '123'
})
console.log(this.state.message)
}
setState设计为异步,可以显著提升性能
1.如果每次调用setState都进行一次更新,那么意味着render函数会被频繁调用,界面重新渲染,效率很低
2.最好的方法是获取多个更新,之后进行批量更新
如果同步更新了state,但是还没有执行render函数,那么state和props不能保持同步
state和props不能保持一致性,会在开发中产生很多问题
获取异步更新后的结果
this.setState({
message: '123'
},()=>{
console.log(this.state.message)
})
componentDidUpdate(){
console.log(this.state.message)
}
setState同步的情况
在组件生命周期和React合成事件中,setState是异步
在setTimeout或者原生dom事件中,setState是同步
changeText() {
setTimeout(()=>{
this.setState({
message: '你好,李银河'
})
console.log(this.state.message)
}, 0)
}
componentDidUpdate(){
const btn = document.getElementByid('btn')
btn.addEventListener('click',()=>{
this.setState({
message: '你好,李银河'
})
console.log(this.state.message)
})
}
setState的数据合并
this.state = {
message: '123',
name: 'coder'
}
changeText() {
this.setState({
message: '你好,李银河'
})
}
setState合并累加
this.setState((prevState,props)=>{
return {
counter: prevState.counter+1
}
})
React更新机制
渲染流程:JSX->虚拟dom->真实dom
更新流程:
props/state改变 -> render函数重新执行 -> 产生新的dom树-> 新旧dom树diff算法 ->计算出差异进行更新 -> 更新到真实dom
1.同层节点之间互相比较,不会跨节点比较
2.不同类型的节点,产生不同的树结构
3.开发中,通过key来指定哪些节点在不同的渲染下保持稳定
使用key注意事项
key应该是唯一的
key不要使用随机数(随机数在下一次render时,会重新生成一个数字)
使用index作为key,对性能是没有优化的
shouldComponentUpdate
nextProps 修改之后最新的props属性
nextState 修改之后最新的state
返回一个boolean类型
true 需要调用render方法
false 不需要调用render方法
shouldComponentUpdate(nextProps, nextState){
if(nextState.count !== this.state.count){
return true;
}
return false;
}
pureComponent
export default class App extends PureComponent {}
const MemoHeader = memo(fucntion Header(){
return <h2>我是header</h2>
})
ref用法
函数式组件没有实列,无法通过ref获取他们的实列
constructor(props){
super(props);
this.titleRef = createRef()
this.titleRef2 = null
}
<div ref={this.titleRef}>123</div>
<div ref={el => this.titleRef2 = el}>456</div>
this.titleRef.current.style.color = 'red'
this.titleRef2.style.color = 'blue'
通过forwardRef高阶函数转发
const ForwardProfile = forwardRef(function(props, ref) {
return (
<div>
<h1 ref={ref}>Profile</h1>
</div>
)
})
高阶函数:接受一个或多个函数作为输入,输出一个函数 filter,map
高阶组件:参数为组件,返回值为新组件的函数
高阶组件不是一个组件,而是一个函数,这个函数的参数是一个组件,
返回值也是一个组件
function higherOrderComponent(wrappercomponent) {
class Newcomponent extends Purecomponent {
render() {
return <wrappercomponent>
}
}
return Newcomponent
}
Portals
渲染的内容独立于父组件,甚至是独立于当前挂载到的DOM元素中
class Modal extends PureComponent{
render(){
return ReactDOM.createPortal(
this.props.children,
document.getElementById("modal")
)
}
}
Fragment 类似<template>
<Fragment></Fragment>或<></>
严格模式
<React.StrictMode>
<App/>
</React.StrictMode>
1.识别不安全的生命周期
2.使用过时的ref API
3.使用废弃的findDOMNode方法
4.检查意外副作用 组件的constructor会被调用两次,生产环境不会