React 原理詳解
1.setState() 說(shuō)明
1.1 更新數(shù)據(jù)
setState() 是異步更新數(shù)據(jù)
可以多次調(diào)用 setState() ,只會(huì)觸發(fā)一次重新渲染
import React from 'react'
import ReactDOM from 'react-dom'
class Opp extends React.Component {
state = {
count: 1,
}
handleClick = () => {
// 異步更新數(shù)據(jù)
this.setState({
count: this.state.count + 1,
})
this.setState({
count: this.state.count + 1,
})
console.log(this.state.count) // 1
}
render() {
return (
<div>
<h1>計(jì)數(shù)器:{this.state.count}</h1>
<button onClick={this.handleClick}>+1</button>
</div>
)
}
}
ReactDOM.render(<Opp />, document.getElementById('root'))
1.2 推薦語(yǔ)法
使用 setState((state,props)=>{}) 語(yǔ)法
state:表示最新的 state, props:表示最新的 props
import React from 'react'
import ReactDOM from 'react-dom'
class Opp extends React.Component {
state = {
count: 1,
}
handleClick = () => {
/* // 異步更新數(shù)據(jù)
this.setState({
count: this.state.count + 1,
})
console.log(this.state.count) //1
this.setState({
count: this.state.count + 1,
})
console.log(this.state.count) //1
*/
// 推薦語(yǔ)法
this.setState((state, props) => {
return {
count: state.count + 1,
}
})
this.setState((state, props) => {
console.log('第二次調(diào)用:', state) //2
return {
count: state.count + 1,
}
})
console.log(this.state.count) // 3
}
render() {
return (
<div>
<h1>計(jì)數(shù)器:{this.state.count}</h1>
<button onClick={this.handleClick}>+1</button>
</div>
)
}
}
ReactDOM.render(<Opp />, document.getElementById('root'))
1.3 第二個(gè)參數(shù)
- 在狀態(tài)更新(頁(yè)面完成重新渲染)后立即執(zhí)行某個(gè)操作
- 語(yǔ)法:setState(updater[,callback])
callback 是指回調(diào)函數(shù) 可加可不加
import React from 'react'
import ReactDOM from 'react-dom'
class Opp extends React.Component {
state = {
count: 1,
}
handleClick = () => {
this.setState(
(state, props) => {
return {
count: state.count + 1,
}
},
// 狀態(tài)更新后并且重新渲染后,立即執(zhí)行
() => {
console.log('狀態(tài)更新完成:', this.state.count) // 2
console.log(document.getElementById('title').innerText) // 計(jì)數(shù)器:2
document.title = '更新后的 count 為:' + this.state.count
}
)
console.log(this.state.count) //1
}
render() {
return (
<div>
<h1 id='title'>計(jì)數(shù)器:{this.state.count}</h1>
<button onClick={this.handleClick}>+1</button>
</div>
)
}
}
ReactDOM.render(<Opp />, document.getElementById('root'))
2.JSX 語(yǔ)法的轉(zhuǎn)化過(guò)程
- JSX 僅僅是 createElement() 方法的語(yǔ)法糖(簡(jiǎn)化語(yǔ)法)
- JSX 語(yǔ)法被 @babel/preset-react 插件編譯為 createElement() 方法
- React元素:是一個(gè)對(duì)象,用來(lái)描述你希望在屏幕上看到的內(nèi)容

import React from 'react'
import ReactDOM from 'react-dom'
// JSX 語(yǔ)法的轉(zhuǎn)化過(guò)程
// const element = <h1 className='greeting'>Hello JSX</h1>
const element = React.createElement(
'h1',
{
className: 'greeting',
},
'Hello JSX'
)
console.log(element)
ReactDOM.render(element, document.getElementById('root'))
3.組件更新機(jī)制
- setState() 的兩個(gè)作用:1.修改 state 2.更新組件(UI)
- 過(guò)程:父組件重新渲染是,也會(huì)重新渲染子組件,但只會(huì)渲染當(dāng)前組件子樹(shù)(當(dāng)前組件及其所有子組件)

4.組件性能優(yōu)化
4.1 減輕 state
- 減輕 state :只存儲(chǔ)跟組件渲染相關(guān)的數(shù)據(jù)(比如:count /列表數(shù)據(jù)/ loading 等)
- 注意:不用渲染的書籍不要放在 state 中(比如定時(shí)器 id 等)
- 需要在多個(gè)方法中用到的數(shù)據(jù),應(yīng)該放在 this 中
4.2 避免不必要的重新渲染
- 組件更新機(jī)制:父組件更新會(huì)引起子組件也被更新
- 問(wèn)題:子組件沒(méi)有變化時(shí)也會(huì)被重新渲染,造成不必要的重新渲染
- 解決方式:使用鉤子函數(shù)shouldComponentUpdate(nextProps,nextState)
- 作用:通過(guò)返回值決定該組件是否重新渲染,返回 true 表示重新渲染, false 表示不重新渲染
- 觸發(fā)時(shí)機(jī):更新階段的鉤子函數(shù),組件重新渲染前執(zhí)行(shouldComponentUpdate -> render)
import React from 'react'
import ReactDOM from 'react-dom'
class Opp extends React.Component {
state = {
count: 0,
}
handleClick = () => {
this.setState((state) => {
return {
count: this.state.count + 1,
}
})
}
// 鉤子函數(shù)
shouldComponentUpdate(nextProps, nextState) {
// 返回 false,阻止組件重新渲染
// return false
// 最新的狀態(tài)
console.log('最新的state', nextState)
// 更新前的狀態(tài)
console.log(this.state)
// 返回 true,組件重新渲染
return true
}
render() {
console.log('組件更新了')
return (
<div>
<h1>計(jì)數(shù)器:{this.state.count}</h1>
<button onClick={this.handleClick}>+1</button>
</div>
)
}
}
ReactDOM.render(<Opp />, document.getElementById('root'))
案例:隨機(jī)數(shù)
通過(guò) nextState
import React from 'react'
import ReactDOM from 'react-dom'
// 生成隨機(jī)數(shù)
class Opp extends React.Component {
state = {
number: 0,
}
handleClick = () => {
this.setState((state) => {
return {
number: Math.floor(Math.random() * 3),
}
})
}
// 兩次生成的隨機(jī)數(shù)可能相同,則沒(méi)必要重新渲染
shouldComponentUpdate(nextState) {
console.log('最新?tīng)顟B(tài):', nextState, '當(dāng)前狀態(tài):', this.state)
return nextState.number !== this.state.number
/* if ( nextState.number !== this.state.number) {
return true
}
return false*/
}
render() {
console.log('render')
return (
<div>
<h1>隨機(jī)數(shù):{this.state.number}</h1>
<button onClick={this.handleClick}>重新生成</button>
</div>
)
}
}
ReactDOM.render(<Opp />, document.getElementById('root'))
通過(guò) nextState
import React from 'react'
import ReactDOM from 'react-dom'
// 生成隨機(jī)數(shù)
class Opp extends React.Component {
state = {
number: 0,
}
handleClick = () => {
this.setState((state) => {
return {
number: Math.floor(Math.random() * 3),
}
})
}
render() {
return (
<div>
<NumberBox number={this.state.number} />
<button onClick={this.handleClick}>重新生成</button>
</div>
)
}
}
class NumberBox extends React.Component {
shouldComponentUpdate(nextProps) {
console.log('最新props:', nextProps, '當(dāng)前props:', this.props)
return nextProps.number !== this.props.number
}
render() {
console.log('子組件render')
return <h1>隨機(jī)數(shù):{this.props.number}</h1>
}
}
ReactDOM.render(<Opp />, document.getElementById('root'))
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
React內(nèi)存泄漏的常見(jiàn)原因及避免策略
內(nèi)存泄漏是指程序中分配的內(nèi)存未能正確釋放,導(dǎo)致內(nèi)存占用不斷增加,最終可能影響應(yīng)用性能甚至崩潰,在React中,內(nèi)存泄漏常發(fā)生于組件卸載后,本文將詳細(xì)介紹內(nèi)存泄漏在React中的常見(jiàn)原因及避免策略,需要的朋友可以參考下2025-03-03
react中使用echarts,并實(shí)現(xiàn)tooltip循環(huán)輪播方式
這篇文章主要介紹了react中使用echarts,并實(shí)現(xiàn)tooltip循環(huán)輪播方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
React通過(guò)父組件傳遞類名給子組件的實(shí)現(xiàn)方法
React 是一個(gè)用于構(gòu)建用戶界面的 JAVASCRIPT 庫(kù)。這篇文章主要介紹了React通過(guò)父組件傳遞類名給子組件的方法,需要的朋友可以參考下2017-11-11
React操作真實(shí)DOM實(shí)現(xiàn)動(dòng)態(tài)吸底部的示例
本篇文章主要介紹了React操作真實(shí)DOM實(shí)現(xiàn)動(dòng)態(tài)吸底部的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
React的createElement和render手寫實(shí)現(xiàn)示例
這篇文章主要為大家介紹了React的createElement和render手寫實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
解決React報(bào)錯(cuò)Property 'X' does not 
這篇文章主要為大家介紹了解決React報(bào)錯(cuò)Property 'X' does not exist on type 'HTMLElement',有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12

