您好,登錄后才能下訂單哦!
今天小編給大家分享一下React生命周期與父子組件間通信知識點有哪些的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
很多的事物都有從創建到銷毀的整個過程,這個過程稱之為是生命周期;
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> <h3>{message}</h3> <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 } } }
如果不初始化 state 或不進行方法綁定,則不需要為 React 組件實現構造函數。
constructor中通常只做兩件事情:
通過給 this.state 賦值對象來初始化內部的state;
為事件綁定實例(this);
componentDidMount() 會在組件掛載后(插入 DOM 樹中)立即調用。
componentDidMount中通常進行哪里操作呢?
依賴于DOM的操作可以在這里進行;
在此處發送網絡請求就最好的地方;(官方建議)
可以在此處添加一些訂閱(會在componentWillUnmount取消訂閱);
componentDidUpdate() 會在更新后會被立即調用,首次渲染不會執行此方法。
當組件更新后,可以在此處對 DOM 進行操作;
如果你對更新前后的 props 進行了比較,也可以選擇在此處進行網絡請求;(例如,當 props 未發生變化時,則不會執行網絡請求)。
componentWillUnmount() 會在組件卸載及銷毀之前直接調用。
在此方法中執行必要的清理操作;
例如,清除 timer,取消網絡請求或清除在 componentDidMount() 中創建的訂閱等;
除了上面介紹的生命周期函數之外,還有一些不常用的生命周期函數:
getDerivedStateFromProps:state 的值在任何時候都依賴于 props時使用;該方法返回一個對象來更新state;
getSnapshotBeforeUpdate:在React更新DOM之前回調的一個函數,可以獲取DOM更新前的一些信息(比如說滾動位置);
shouldComponentUpdate:該生命周期函數很常用,但是我們等待講性能優化時再來詳細講解;
另外,React中還提供了一些過期的生命周期函數,這些函數已經不推薦使用。
在開發過程中,我們會經常遇到需要組件之間相互進行通信:
比如App可能使用了多個Header,每個地方的Header展示的內容不同,那么我們就需要使用者傳遞給Header一些數據,讓其進行展示;
又比如我們在Main中一次性請求了Banner數據和ProductList數據,那么就需要傳遞給他們來進行展示;
也可能是子組件中發生了事件,需要由父組件來完成某些操作,那就需要子組件向父組件傳遞事件;
總之,在一個React項目中,組件之間的通信是非常重要的環節;
父組件在展示子組件,可能會傳遞一些數據給子組件:
父組件通過 屬性=值 的形式來傳遞給子組件數據;
子組件通過 props 參數獲取父組件傳遞過來的數據。
對于傳遞給子組件的數據,有時候我們可能希望進行驗證,特別是對于大型項目來說:
當然,如果你項目中默認繼承了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 };
您可以通過配置特定的 defaultProps 屬性來定義 props 的默認值:
class Greeting extends React.Component { render() { return ( <h2>Hello, {this.props.name}</h2> ); } } // 指定 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> <h3>當前計數: {counter}</h3> <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
以上就是“React生命周期與父子組件間通信知識點有哪些”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。