網站首頁 編程語言 正文
聲明周期
很多的事物都有從創建到銷毀的整個過程,這個過程稱之為是生命周期;
React組件也有自己的生命周期,了解組件的生命周期可以讓我們在最合適的地方完成自己想要的功能;
生命周期和生命周期函數的關系:
生命周期是一個抽象的概念,在生命周期的整個過程,分成了很多個階段;
比如裝載階段(Mount),組件第一次在DOM樹中被渲染的過程;
比如更新過程(Update),組件狀態發生變化,重新更新渲染的過程;
比如卸載過程(Unmount),組件從DOM樹中被移除的過程;
React內部為了告訴我們當前處于哪些階段,會對我們組件內部實現的某些函數進行回調,這些函數就是生命周期函數:
比如實現componentDidMount函數:組件已經掛載到DOM上時,就會回調;
比如實現componentDidUpdate函數:組件已經發生了更新時,就會回調;
比如實現componentWillUnmount函數:組件即將被移除時,就會回調;
我們可以在這些回調函數中編寫自己的邏輯代碼,來完成自己的需求功能;
我們談React生命周期時,主要談的類的生命周期,因為函數式組件是沒有生命周期函數的
聲明周期解析
我們先來了解一下最基礎、最常用的生命周期函數:
生命周期函數
class HelloWorld extends React.Component {
// 1.構造方法: constructor
constructor() {
console.log("HelloWorld constructor")
super()
this.state = {
message: "Hello World"
}
}
changeText() {
this.setState({ message: "你好啊, 李銀河" })
}
// 2.執行render函數
render() {
console.log("HelloWorld render")
const { message } = this.state
return (
<div>
<h2>{message}</h2>
<p>{message}是程序員的第一個代碼!</p>
<button onClick={e => this.changeText()}>修改文本</button>
</div>
)
}
// 3.組件被渲染到DOM: 被掛載到DOM
componentDidMount() {
console.log("HelloWorld componentDidMount")
}
// 4.組件的DOM被更新完成: DOM發生更新
componentDidUpdate(prevProps, prevState, snapshot) {
console.log("HelloWorld componentDidUpdate:", prevProps, prevState, snapshot)
}
// 5.組件從DOM中卸載掉: 從DOM移除掉
componentWillUnmount() {
console.log("HelloWorld componentWillUnmount")
}
// 不常用的生命周期補充
shouldComponentUpdate() {
return true
}
getSnapshotBeforeUpdate() {
console.log("getSnapshotBeforeUpdate")
return {
scrollPosition: 1000
}
}
}
Constructor
如果不初始化 state 或不進行方法綁定,則不需要為 React 組件實現構造函數。
constructor中通常只做兩件事情:
通過給 this.state 賦值對象來初始化內部的state;
為事件綁定實例(this);
componentDidMount
componentDidMount() 會在組件掛載后(插入 DOM 樹中)立即調用。
componentDidMount中通常進行哪里操作呢?
依賴于DOM的操作可以在這里進行;
在此處發送網絡請求就最好的地方;(官方建議)
可以在此處添加一些訂閱(會在componentWillUnmount取消訂閱);
componentDidUpdate
componentDidUpdate() 會在更新后會被立即調用,首次渲染不會執行此方法。
當組件更新后,可以在此處對 DOM 進行操作;
如果你對更新前后的 props 進行了比較,也可以選擇在此處進行網絡請求;(例如,當 props 未發生變化時,則不會執行網絡請求)。
componentWillUnmount
componentWillUnmount() 會在組件卸載及銷毀之前直接調用。
在此方法中執行必要的清理操作;
例如,清除 timer,取消網絡請求或清除在 componentDidMount() 中創建的訂閱等;
不常用的生命周期函數
除了上面介紹的生命周期函數之外,還有一些不常用的生命周期函數:
getDerivedStateFromProps:state 的值在任何時候都依賴于 props時使用;該方法返回一個對象來更新state;
getSnapshotBeforeUpdate:在React更新DOM之前回調的一個函數,可以獲取DOM更新前的一些信息(比如說滾動位置);
shouldComponentUpdate:該生命周期函數很常用,但是我們等待講性能優化時再來詳細講解;
另外,React中還提供了一些過期的生命周期函數,這些函數已經不推薦使用。
認識組件間的通信
在開發過程中,我們會經常遇到需要組件之間相互進行通信:
比如App可能使用了多個Header,每個地方的Header展示的內容不同,那么我們就需要使用者傳遞給Header一些數據,讓其進行展示;
又比如我們在Main中一次性請求了Banner數據和ProductList數據,那么就需要傳遞給他們來進行展示;
也可能是子組件中發生了事件,需要由父組件來完成某些操作,那就需要子組件向父組件傳遞事件;
總之,在一個React項目中,組件之間的通信是非常重要的環節;
父組件在展示子組件,可能會傳遞一些數據給子組件:
父組件通過 屬性=值 的形式來傳遞給子組件數據;
子組件通過 props 參數獲取父組件傳遞過來的數據;
參數propTypes
對于傳遞給子組件的數據,有時候我們可能希望進行驗證,特別是對于大型項目來說:
當然,如果你項目中默認繼承了Flow或者TypeScript,那么直接就可以進行類型驗證;
但是,即使我們沒有使用Flow或者TypeScript,也可以通過 prop-types 庫來進行參數驗證;
從 React v15.5 開始,React.PropTypes 已移入另一個包中:prop-types 庫
import PropTypes from 'prop-types';
MyComponent.propTypes = {
// 你可以將屬性聲明為 JS 原生類型,默認情況下
// 這些屬性都是可選的。
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
// 任何可被渲染的元素(包括數字、字符串、元素或數組)
// (或 Fragment) 也包含這些類型。
optionalNode: PropTypes.node,
// 一個 React 元素。
optionalElement: PropTypes.element,
// 一個 React 元素類型(即,MyComponent)。
optionalElementType: PropTypes.elementType,
// 你也可以聲明 prop 為類的實例,這里使用
// JS 的 instanceof 操作符。
optionalMessage: PropTypes.instanceOf(Message),
// 你可以讓你的 prop 只能是特定的值,指定它為
// 枚舉類型。
optionalEnum: PropTypes.oneOf(['News', 'Photos']),
// 一個對象可以是幾種類型中的任意一個類型
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message)
]),
// 可以指定一個數組由某一類型的元素組成
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
// 可以指定一個對象由某一類型的值組成
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
// 可以指定一個對象由特定的類型值組成
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
// An object with warnings on extra properties
optionalObjectWithStrictShape: PropTypes.exact({
name: PropTypes.string,
quantity: PropTypes.number
}),
// 你可以在任何 PropTypes 屬性后面加上 `isRequired` ,確保
// 這個 prop 沒有被提供時,會打印警告信息。
requiredFunc: PropTypes.func.isRequired,
// 任意類型的必需數據
requiredAny: PropTypes.any.isRequired,
// 你可以指定一個自定義驗證器。它在驗證失敗時應返回一個 Error 對象。
// 請不要使用 `console.warn` 或拋出異常,因為這在 `oneOfType` 中不會起作用。
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},
// 你也可以提供一個自定義的 `arrayOf` 或 `objectOf` 驗證器。
// 它應該在驗證失敗時返回一個 Error 對象。
// 驗證器將驗證數組或對象中的每個值。驗證器的前兩個參數
// 第一個是數組或對象本身
// 第二個是他們當前的鍵。
customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (!/matchme/.test(propValue[key])) {
return new Error(
'Invalid prop `' + propFullName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
})
};
限制單個元素
你可以通過 PropTypes.element 來確保傳遞給組件的 children 中只包含一個元素。
import PropTypes from 'prop-types';
class MyComponent extends React.Component {
render() {
// 這必須只有一個元素,否則控制臺會打印警告。
const children = this.props.children;
return (
<div>
{children}
</div>
);
}
}
MyComponent.propTypes = {
children: PropTypes.element.isRequired
};
默認 Prop 值
您可以通過配置特定的 defaultProps 屬性來定義 props 的默認值:
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
// 指定 props 的默認值:
Greeting.defaultProps = {
name: 'Stranger'
};
// 渲染出 "Hello, Stranger":
const root = ReactDOM.createRoot(document.getElementById('example'));
root.render(<Greeting />);
從 ES2022 開始,你也可以在 React 類組件中將 defaultProps 聲明為靜態屬性。這種現代語法需要添加額外的編譯步驟才能在老版瀏覽器中工作。
class Greeting extends React.Component {
static defaultProps = {
name: 'stranger'
}
render() {
return (
<div>Hello, {this.props.name}</div>
)
}
}
defaultProps 用于確保 this.props.name 在父組件沒有指定其值時,有一個默認值。propTypes 類型檢查發生在 defaultProps 賦值后,所以類型檢查也適用于 defaultProps
對于函數式組件
如果你在常規開發中使用函數組件,那你可能需要做一些適當的改動,以保證 PropsTypes 應用正常。
假設你有如下組件:
export default function HelloWorldComponent({ name }) {
return (
<div>Hello, {name}</div>
)
}
如果要添加 PropTypes,你可能需要在導出之前以單獨聲明的一個函數的形式,聲明該組件,具體代碼如下:
function HelloWorldComponent({ name }) {
return (
<div>Hello, {name}</div>
)
}
export default HelloWorldComponent
接著,可以直接在 HelloWorldComponent 上添加 PropTypes:
import PropTypes from 'prop-types'
function HelloWorldComponent({ name }) {
return (
<div>Hello, {name}</div>
)
}
HelloWorldComponent.propTypes = {
name: PropTypes.string
}
export default HelloWorldComponent
子組件傳遞父組件
某些情況,我們也需要子組件向父組件傳遞消息:
在vue中是通過自定義事件來完成的;
在React中同樣是通過props傳遞消息,只是讓父組件給子組件傳遞一個回調函數,在子組件中調用這個函數即可;
我們這里來完成一個案例:
將計數器案例進行拆解;
將按鈕封裝到子組件中:CounterButton;
CounterButton發生點擊事件,將內容傳遞到父組件中,修改counter的值;
app.jsx
import React, { Component } from 'react'
import AddCounter from './AddCounter'
import SubCounter from './SubCounter'
export class App extends Component {
constructor() {
super()
this.state = {
counter: 100
}
}
changeCounter(count) {
this.setState({ counter: this.state.counter + count })
}
render() {
const { counter } = this.state
return (
<div>
<h2>當前計數: {counter}</h2>
<AddCounter addClick={(count) => this.changeCounter(count)}/>
<SubCounter subClick={(count) => this.changeCounter(count)}/>
</div>
)
}
}
export default App
subCounter.jsx
import React, { Component } from 'react'
export class SubCounter extends Component {
subCount(count) {
this.props.subClick(count)
}
render() {
return (
<div>
<button onClick={e => this.subCount(-1)}>-1</button>
<button onClick={e => this.subCount(-5)}>-5</button>
<button onClick={e => this.subCount(-10)}>-10</button>
</div>
)
}
}
export default SubCounter
addCounter.jsx
import React, { Component } from 'react'
// import PropTypes from "prop-types"
export class AddCounter extends Component {
addCount(count) {
this.props.addClick(count)
}
render() {
return (
<div>
<button onClick={e => this.addCount(1)}>+1</button>
<button onClick={e => this.addCount(5)}>+5</button>
<button onClick={e => this.addCount(10)}>+10</button>
</div>
)
}
}
// AddCounter.propTypes = {
// addClick: PropTypes.func
// }
export default AddCounter
原文鏈接:https://blog.csdn.net/weixin_65402230/article/details/128063611
相關推薦
- 2022-07-30 Golang?獲取系統信息的實現_Golang
- 2022-06-22 React表單容器的通用解決方案_React
- 2022-08-01 OpenCV連通域數量統計學習示例_python
- 2022-04-18 python?dataframe實現統計行列中零值的個數_python
- 2022-02-17 uni-app的 tabBar添加陰影
- 2022-09-01 Docker鏡像的遷移與備份及Dockerflie?使用方法詳解_docker
- 2022-04-21 sql更新語句中update?set?from用法實現_MsSql
- 2022-12-06 python中的代碼運行時間獲取方式_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支