react只停留在表层?五大知识点带你梳理进阶知识
五大知識點帶你梳理react進階知識
- ??前言
- 📧一、props
- 1、PropTypes與DefaultProps應(yīng)用
- (1)PropTypes
- (2)defaultProps
 
- 2、props,state與render函數(shù)
 
- 📨二、React中的虛擬DOM
- 1、什么是虛擬DOM
- (1)第一種方案
- (2)第二種方案
- (3)第三種方案
 
- 2、虛擬DOM中的 Diff 算法
 
- 📩三、React中ref的使用
- 📦四、React中的生命周期
- 1、生命周期函數(shù)是什么
- 2、生命周期圖例
 
- 📪五、React中使用CSS動畫效果
- 1、普通用法
- 2、react-transition-group
- (1)初次探索
- (2)進階探索
 
 
- 📮六、結(jié)束語
- 🗳?彩蛋
??前言
對于 react 的表層來說,我們可能經(jīng)常聽說的是聲明式開發(fā)、單向數(shù)據(jù)流、組件化方式開發(fā)等等。那么,進一步來講的話,我們還需要了解的是 react 的 props ,虛擬 DOM 、 ref 以及過渡動畫等更多新的知識點。
那在下面的這篇文章中,將來探索關(guān)于 react 的進階知識。
叮,下面開始本文的介紹~🤪
📧一、props
1、PropTypes與DefaultProps應(yīng)用
(1)PropTypes
在 react 中,有時候我們要對組件中的某個屬性進行格式校驗,這個時候我們就需要用到 propTypes 。下面給出一些常見的例子:
// 表示要對TodoItem這個組件做屬性的校驗 TodoItem.propTypes = {// isRequired 表示必須有值test: PropTypes.string.isRequired,// 表示content的propTypes必須是string類型,那string類型的校驗是從PropTypes這個包里面拿到的content: PropTypes.string,// 表示detail可以是一個number或者string的語法detail: PropTypes.arrayOf(PropTypes.number, PropTypes.string),// 表示deleteItem必須是一個函數(shù)deleteItem: PropTypes.func,// 表示index必須是一個數(shù)字類型index: PropTypes.number }(2)defaultProps
有時候,對于某個屬性來說,我們希望給它個初始值,那這個時候就需要用到 defaultProps 。示例如下:
TodoItem.defaultProps = {test: 'hello world' }上面的代碼表明,當 test 屬性沒有被賦值時,那么它將被賦予一個初始值,值為 hello world 。
2、props,state與render函數(shù)
在 react 中,定義一個組件時,經(jīng)常會看到 props 、 state 和 render 。那他們?nèi)呤窃趺礃拥年P(guān)系呢?
首先我們要想一個問題:為什么數(shù)據(jù)發(fā)生變化,頁面就會跟著變化呢?
原因在于,頁面是由 render 函數(shù)渲染出來的,當數(shù)據(jù) state 發(fā)生變化時, render 函數(shù)就會被重新的執(zhí)行一次。
同時,當父組件的 render 函數(shù)被運行時,它的子組件的 render 都將被重新運行。
📨二、React中的虛擬DOM
1、什么是虛擬DOM
(1)第一種方案
傳統(tǒng)實現(xiàn)虛擬 DOM 的思路:
- 先定義 state ,也就是數(shù)據(jù);
- 編寫JSX 模板內(nèi)容;
- 把數(shù)據(jù)和模板進行結(jié)合,生成真是的 DOM ,進而將內(nèi)容顯示到頁面上;
- 如果遇到要替換數(shù)據(jù)時,則把數(shù)據(jù)和模板進行結(jié)合,生成真實的 DOM ,來替換原始的 DOM 。
存在缺陷:
- 第一次生成了一個完整的 DOM 片段;
- 第二次又生成了一個完整的 DOM 片段;
- 第二次的 DOM 替換第一次的 DOM ,非常耗費性能。
(2)第二種方案
傳統(tǒng)實現(xiàn)虛擬 DOM 的思路改進版:
- 先定義 state ,即數(shù)據(jù);
- 編寫 JSX 模板內(nèi)容;
- 把數(shù)據(jù)和模板進行結(jié)合,生成真實的 DOM ,并展示;
- 當 state 的數(shù)據(jù)發(fā)生改變;
- 繼續(xù),把數(shù)據(jù)和模板進行結(jié)合,生成真實的 DOM ,并不是直接替換原始的 DOM
- 將新的 DOM 和原始的 DOM 做比較,并找出差異;
- 找到新的 Dom 中發(fā)生的變化;
- 只用新的 DOM 中變化的數(shù)據(jù),來替換掉老的 DOM 中的數(shù)據(jù)。
存在缺陷:
- 性能的提升并不明顯
(3)第三種方案
react 中實現(xiàn)虛擬 DOM 的思路:
-  先定義 state ,即數(shù)據(jù); 
-  編寫 JSX 模板內(nèi)容; 
-  把數(shù)據(jù)和模板進行結(jié)合,生成虛擬 DOM (虛擬 DOM 就是一個 JS 對象,用它來描述真實 DOM )。👉(損耗了性能) <div id="abc"><span>hello world</span></div> ['div', {id: 'abc'}, ['span', {}, 'hello world']]
-  用虛擬 DOM 的結(jié)構(gòu)生成真實的 DOM ,來進行顯示; 
-  當 state 發(fā)生變化時,數(shù)據(jù) + 模板生成新的虛擬 DOM ;👉(極大的提升了性能) 
- 比較 原始虛擬 DOM 和 新的虛擬 DOM 的區(qū)別,找到其中的區(qū)別是 span 中的內(nèi)容;
- 直接操作 DOM ,改變 span 的內(nèi)容;
- 因此, React 的虛擬 DOM 主要經(jīng)歷的過程是: JSX → createElement → 虛擬 DOM ( JS 對象 )→ 真實的 DOM 。
react 虛擬 DOM 的優(yōu)點:
- 極大的提升了性能;
- 它使得跨端應(yīng)用得以實現(xiàn),這要談到 react 中的一個概念,react native ;
- react 使用可以編寫原生應(yīng)用,像 Android 和 IOS 開發(fā),這些都是操作真實 DOM ;
- 而 react 使得編寫這些原生應(yīng)用得以使用。
2、虛擬DOM中的 Diff 算法
- react 對 setState 的性能優(yōu)化,它會把多次 setState 結(jié)合成一次 setState ;
- 虛擬 DOM 使用 diff 算法做比較,只在同層做比較,不跨級做比較;
- 同層比對的算法比較簡單,而算法簡單帶來的直接好處就是速度非常快;
- 雖然可能會造成 DOM 渲染上的一些浪費,但是呢,它也極大的減少了兩個虛擬 DOM 之間進行比較時,性能上的消耗。
📩三、React中ref的使用
react 中建議的是,希望我們可以用數(shù)據(jù)驅(qū)動的形式來編寫代碼,盡量不要操作 DOM 。但有時候,我們在做一些極其復雜業(yè)務(wù)的時候,比如各種震撼動畫,不可避免的還是會用到一些原生的 DOM 標簽。因此, ref 幫助我們在 react 中直接獲取 DOM 元素的時候來進行使用。
一般情況下,我們盡量不使用 ref 。如果用 ref 時,會出現(xiàn)各種各樣的問題。同時,當使用 ref 和 setState 時,要注意一些存在的坑。
比如,當 ref 與 setState 相關(guān)聯(lián)使用時,要注意, setState 是一個異步函數(shù),往往會在同步代碼執(zhí)行完畢后再執(zhí)行異步代碼。因此,如果我們希望同步代碼執(zhí)行順序在 setState 之后時,可以在 setState 接受的第二個參數(shù)中,再增加一個回調(diào)函數(shù)來進行調(diào)用,這樣就可以達到我們的效果啦!
render() {return (<ul ref={(ul) => this.ul = ul}>{this.getTodoItem()}</ul>) }this.setState((prevState) => ({list: [...prevState.list, prevState.inputValue],inputValue: '' }), () => {console.log(this.ul.querySelectorAll('div').length) });📦四、React中的生命周期
1、生命周期函數(shù)是什么
所謂生命周期函數(shù),指的是在某一個時刻,組件會自動調(diào)用執(zhí)行的函數(shù)。那 react 的生命周期都有哪一些呢?
| Mounting | componentWillMount | ①當組件即將被掛載到頁面的時刻時自動執(zhí)行,即在頁面掛在之前執(zhí)行;②只在組件被第一次掛在到頁面上才會執(zhí)行; | 
| Mounting/Updation | render | 頁面掛載時被執(zhí)行 | 
| Mounting | componentDidMount | 會在組件被掛載到頁面之后,自動被執(zhí)行;只在組件被第一次掛在到頁面上才會執(zhí)行 | 
| Updation | componentWillReceiveProps | ①當一個組件從父組件接收參數(shù);②只要父組件的render函數(shù)被執(zhí)行了,子組件的這個生命周期函數(shù)就會被執(zhí)行;③如果這個組件第一次存在于父組件中,不會執(zhí)行;④如果這個組件之前已經(jīng)存在于父組件中,才會被執(zhí)行; | 
| Updation | componentWillUpdate | ①組件被更新之前,她會自動執(zhí)行;②但是它是在shouldComponentUpdate之后被執(zhí)行,如果shouldComponentUpdate返回true時,它才執(zhí)行;如果返回false,這個函數(shù)就不會被執(zhí)行了。 | 
| Updation | componentDidUpdate | 組件更新完成之后,它會被執(zhí)行。 | 
| Updation | shouldComponentUpdate | 組件被更新之前,它會被自動被執(zhí)行;此生命周期返回一個布爾值 | 
| Unmounting | componentWillUnmount | 當這個組件即將被從頁面中剔除的時候,會被執(zhí)行。 | 
2、生命周期圖例
下面用一張圖來展示 react 中生命周期的執(zhí)行效果:
📪五、React中使用CSS動畫效果
1、普通用法
我們來看一下,在 react 中,如何使用 css3 所提供的動畫效果。具體代碼如下:
.show {animation: show-item 2s ease-in forwards; }.hide {animation: hide-item 2s wase-in forwards; }@keyframes show-item {0% {oppacity: 0;color: red;}50% {opacity: 0.5;color: green;}100% {opacity: 1;color: blue;} }2、react-transition-group
(1)初次探索
有時候,我們可能會想要實現(xiàn)一些很復雜的動畫,這個時候 css3 提供的是不夠的。因此,我們還需要一點 js 來加以輔助實現(xiàn)更為復雜的動畫。這個時候就有談到 react 中的 react-transition-group 動畫。
假設(shè)我們想要實現(xiàn),當點擊一個按鈕時,一行文字漸隱漸顯的實現(xiàn),那該怎么處理呢?
首先,我們在項目的 src 文件夾下新增一個組件,命名為 App.js 。具體代碼如下:
import React, { Component, Fragment } from 'react'; import { CSSTransition } from 'react-transition-group'; import './style.css';class App extends Component {constructor(props) {super(props);this.state = {show: true}this.handleToggle = this.handleToggle.bind(this);}render() {return (<Fragment>{/* onEntered指的是在某一個時刻會自動執(zhí)行的一個函數(shù)當入場動畫結(jié)束時,onEntered將會被執(zhí)行*/}<CSSTransitionin={this.state.show}timeout={1000}classNames='fade'unmountOnExitonEntered={(el) => { el.style.color = "blue" }}appear={true}><div>hello</div></CSSTransition><button onClick={this.handleToggle}>toggle</button></Fragment>)}handleToggle() {this.setState({show: this.state.show ? false : true})} }export default App;之后新增一個 CSS 文件,命名為 style.css 。具體代碼如下:
/* 入場動畫執(zhí)行的第一個時刻,即剛要入場的這個瞬間 */ /* fade-appear用于實現(xiàn)漸隱漸現(xiàn)的效果 */ .fade-enter, .fade-appear {opacity: 0; }/* 入場動畫執(zhí)行的第二個時刻,到入場動畫執(zhí)行完成之前的一個時刻 */ .fade-enter-active, .fade-appear-active {opacity: 1;transition: opacity 1s ease-in; }/* 當整個入場動畫執(zhí)行完成之后 */ .fade-enter-done {opacity: 1; }/* 表示出場動畫執(zhí)行的第一個時刻 */ .fade-exit {opacity: 1; }/* 整個出場的過程 */ .fade-exit-active {opacity: 0;transition: opacity 1s ease-in; }/* 當整個出場動畫執(zhí)行完成時 */ .fade-exit-done { }此時我們來看下瀏覽器的顯示效果:
(2)進階探索
上面我們只是改變了一項數(shù)據(jù)。現(xiàn)在,如果我們想要點擊就新增一項過渡效果,這又該如何處理呢?
我們來改造下 App.js 文件的代碼。具體代碼如下:
import React, { Component, Fragment } from 'react'; import { CSSTransition, TransitionGroup } from 'react-transition-group'; import './style.css';class App extends Component {constructor(props) {super(props);this.state = {show: true,list: []}this.handleToggle = this.handleToggle.bind(this);}render() {return (<Fragment>{/* onEntered指的是在某一個時刻會自動執(zhí)行的一個函數(shù)當入場動畫結(jié)束時,onEntered將會被執(zhí)行*/}<TransitionGroup>{this.state.list.map((item, index) => {return (<CSSTransitionin={this.state.show}timeout={1000}classNames='fade'unmountOnExitonEntered={(el) => { el.style.color = "blue" }}appear={true}key={index}><div>{item}</div></CSSTransition>)})}</TransitionGroup><button onClick={this.handleToggle}>toggle</button></Fragment>)}handleToggle() {this.setState((prevState) => {return {list: [...prevState.list, 'item']}})} }export default App;此時瀏覽器的運行效果如下:
對于這種類型的動畫來說,我們通過 TransitionGroup 對外層進行包裹,之后通過 CSSTransition 對里層進行包裹,進而達到我們最終的效果。
📮六、結(jié)束語
在上面這篇文章中,我們講解了 react 中的 props ,同時,還簡單的了解了虛擬 DOM 的內(nèi)容。除此之外呢,還學習了 ref 的使用,以及 react 中的酷炫的過渡動畫。當然,最為重要的一點是, react 中的生命周期函數(shù)。
那到這里, react 的進階知識講到這里就結(jié)束了。不知道小伙伴們對 react 是否又有進一步的認識呢?
🗳?彩蛋
- 關(guān)注公眾號星期一研究室,第一時間關(guān)注優(yōu)質(zhì)文章,更有面試專欄待你解鎖~
- 如果您覺得這篇文章有幫助到您的的話不妨點贊支持一下喲~~😉
- 以上就是本文的全部內(nèi)容!我們下期見!🥂🥂🥂
總結(jié)
以上是生活随笔為你收集整理的react只停留在表层?五大知识点带你梳理进阶知识的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 女生轻薄本怎么选如何选择女生电脑
- 下一篇: 新买的固态硬盘怎么分区最合理新买的固态硬
