摘要:對于最開始關(guān)注的是的初始化以及在哪里請求。在進行初始化,推薦在中進行請求。是在組件即將被卸載前一刻的鉤子,一般用于取消中訂閱的事件等作用,清理一些不要的變量等,避免內(nèi)存泄漏。第二條的原因額,說好的更新才調(diào),初始化不調(diào)用是符合邏輯的。
前言
在上篇文章React 導(dǎo)讀(一)中學(xué)習(xí)到了寫第一個 Web 組件,這篇文章將繼續(xù)之前的目錄,開始新的知識點補充:
[x] React 如何編寫 Hello World!
[x] React 中三個最基礎(chǔ)、最重要的東西
[x] React 中的 JSX
[x] 你的第一個 Web 組件
[ ]React 中最開始需要關(guān)注的生命周期
[ ]React 一個組件集合的簡單交互
[ ]React 開始一個項目的一點建議
[ ]React 簡單的項目結(jié)構(gòu)組織
五、React 中最開始需要關(guān)注的生命周期其實在學(xué)習(xí) React 之前,就應(yīng)該了解目前前端推薦的是組件化開發(fā)的方式,React 是讓組件化更加簡單的庫。那么組件開發(fā)必不可少的就是生命周期,說直白一點就是運行組件的過程是 React 來做,運行過程中需要有一些代碼鉤子來讓我們?nèi)フ{(diào)用,在組件執(zhí)行的某一個地方去執(zhí)行我們自己寫的代碼。這里先介紹擁有的生命周期鉤子,下面的方法 constructor 和 render 不屬于生命周期,我按功能分類了一下,也就是學(xué)習(xí)的時候不一定要按部就班,應(yīng)該以學(xué)習(xí)之后能真正寫一些東西為目標(biāo):
(1) 與組件掛載相關(guān)的方法,包括構(gòu)造函數(shù)
constructor
componentWillMount
componentDidMount
componentWillUnmount
最常用的生命周期應(yīng)該是最后 2 個,constructor 和 componentWillMount 目前先理解成能滿足的功能大體相同,如果這里解釋太復(fù)雜不太好。
對于最開始關(guān)注的是:this.state 的初始化以及 ajax 在哪里請求。
this.state 在 constructor 進行初始化,ajax 推薦在 componentDidMount 中進行請求。
componentDidMount 就是在組件已經(jīng)掛載到 DOM 中后的鉤子,可以理解為 jQuery 中提供的 ready 方法。
componentWillUnmount 是在組件即將被卸載前一刻的鉤子,一般用于取消 componentDidMount 中訂閱的事件等作用,清理一些不要的變量等,避免內(nèi)存泄漏。
下面通過一個簡單的例子說明一下:
先有一個 foods.json 文件來模擬請求的后臺數(shù)據(jù)。
[ { "id": 1, "name": "香蕉" }, { "id": 2, "name": "蘋果" }, { "id": 3, "name": "獼猴桃" } ]
// 1. 掛載相關(guān)的生命周期 class CycleMount extends React.Component { constructor() { super(); this.state = { foods: [] }; console.log("1. constructor 執(zhí)行了..."); } componentDidMount() { // 這里使用原生的 fetch API 進行 ajax 請求,你也可以使用 $.ajax 進行請求,原理是一樣的,重點是關(guān)注 setState 的地方 fetch("/mock/foods.json", { method: "GET", headers: new Headers({ "Accept": "application/json" }) } ).then(dataResult => { if(dataResult.status === 200) { return dataResult.json(); } else { return []; } }).then(data => { // 這里的 data 就是 foods.json 里面的數(shù)據(jù) // 調(diào)用 setState 來更新 render 里面調(diào)用的 this.state 的值 this.setState({ foods: data }); }); console.log("2. componentDidMount 執(zhí)行了..."); } render() { // foods 是一個數(shù)組,map 方法是數(shù)組自帶的方法,可以查詢相關(guān) api const foodItems = this.state.foods.map(food => { return (
上面有了完整的注釋,也能看到基本上項目中可能會將代碼寫到何處,我也打了兩個日志,來識別到底是誰先執(zhí)行,結(jié)果可以自己運行一下,執(zhí)行順序就是我標(biāo)記的1,2。
好了,基本的學(xué)習(xí)了,可以自己動手試試訂閱一個事件,然后在卸載的時候取消這個事件。
(2) 優(yōu)化相關(guān)
shouldComponentUpdate
這個方法比較重要,但是我這里不會介紹得太過于復(fù)雜,太復(fù)雜只會讓重要的部分不那么突出。這個方法的返回值是一個 boolean 類型,分別代碼的意義:
true 組件應(yīng)該更新,執(zhí)行 render 方法以及相關(guān)生命周期;
false 組件狀態(tài)沒有更新,不執(zhí)行 render 等方法,意味著網(wǎng)頁界面不會改變。
那么它直觀上的作用是能夠通過返回值來決定界面是否改變,實際的意義就是當(dāng)我們知道當(dāng)前 oldState = this.state 的值和新的 newState = this.state 值完全相等的時候(或者是新傳入的 props)就不用再浪費性能去重新渲染組件了。
API 上的定義是這樣的:
/* nextProps: 新的 props, nextState: 新的 state */ shouldComponentUpdate(nextProps, nextState): boolean
舉個例子來直觀說明一下:
class ComponentOptimize extends React.Component { state = { count: 0 }; shouldComponentUpdate(nextProps, nextState) { // 當(dāng) count > 10 的時候就不能再重新渲染組件了 if(nextState.count > 10) { return false; } return true; } handleUpdateCount() { console.log("我點了一下哦!"); this.setState(prevState => { return { count: prevState.count + 1 }; }); } render() { return (); } }{this.state.count}
你會發(fā)現(xiàn) 10 過后界面就沒有再更新過了,這樣應(yīng)該很直觀了。
(3) Props 相關(guān)的生命周期
componentWillReceiveProps
這個主要是在組件的 props 傳入新的值后被調(diào)用,不管是不是傳的一樣的值或者 shouldComponentUpdate 返回了 false,看下例子吧:
class Cat extends React.Component { componentWillReceiveProps(nextProps) { console.log("改一次我執(zhí)行一次!"); } shouldComponentUpdate(nextProps, nextState) { // 改的名字一樣的時候 return this.props.name !== nextProps.name; } render() { console.log("貓改了一次名字!"); return (我有新名字了!{this.props.name}
); } } class App extends React.Component { state = { catName: "嚕嚕" }; handleChangeCatName() { const catNames = ["嚕嚕", "小白", "小黃", "小黑", "皮卡丘"]; const catIndex = this.getSomeOneIndex(); this.setState({ catName: catNames[catIndex] }); } getSomeOneIndex() { return Math.floor(Math.random() * 5 + 0); } render() { return ({/* 給 Cat 傳新的名字 */}); } }
最后肯定每次點擊按鈕都會輸出這句的結(jié)果 console.log("改一次我執(zhí)行一次!");。
(4) 更新組件相關(guān)
componentWillUpdate
componentDidUpdate
因為都是講解 API,所以國際慣例的先看下 API 的定義吧:
// 組件更新前執(zhí)行 componentWillUpdate(nextProps, nextState) // 組件更新后執(zhí)行 componentDidUpdate(prevProps, prevState)
可以從定義中看出,它們都接受了兩個參數(shù):props && state,不過看變量前綴能夠聯(lián)想點什么。
暫時想不到什么實際項目的例子,隨便假設(shè)點內(nèi)容吧。不過這里需要注意的地方是:
1. 這兩個方法里面都不要調(diào)用 setState!
2. 第一次初始化組件 render 的時候不會執(zhí)行
3. shouldComponentUpdate 返回 false 不會執(zhí)行
第一條的原因:容易形成一個遞歸的調(diào)用,不作就不會死...所以盡量不要在這里調(diào)~目前還沒有碰到需要在這里調(diào)的需求。
第二條的原因:額,說好的更新才調(diào),初始化不調(diào)用是符合邏輯的。
第三條的原因:額,這 2 個鉤子是與組件更新相關(guān)的,所以也符合邏輯的,組件是否更新就是靠 shouldComponentUpdate 返回值。
在上面 Cat 的例子中加入下面的代碼可以看下結(jié)果:
componentWillUpdate() { console.log("componentWillUpdate 執(zhí)行了!") } componentDidUpdate() { console.log("componentDidUpdate 執(zhí)行了!") }
(5)組件錯誤
componentDidCatch
就是在組件發(fā)生異常的時候可能會被調(diào)用的鉤子,需要注意的有下面的地方:
只能在父級組件捕獲子組件的異常;
如果異常被 try...catch 包裹父級組件的鉤子就不會執(zhí)行了。
看個例子吧:
class Cat extends React.Component { componentWillReceiveProps(nextProps) { // 這里手動拋一個異常,觸發(fā)我們的鉤子 componentDidCatch throw new Error("miao miao~"); } render() { let miao = this.props.name; return ({miao}); } } class App extends React.Component { state = { catName: "嚕嚕", isError: false, }; handleChangeCatName() { const catNames = ["嚕嚕", "小白", "小黃", "小黑", "皮卡丘"]; const catIndex = this.getSomeOneIndex(); this.setState({ catName: catNames[catIndex] }); } getSomeOneIndex() { return Math.floor(Math.random() * 5 + 0); } componentDidCatch(error, info) { console.log(error, info); if(error) { // 如果有錯誤信息,就重新渲染一下組件,可能是更好的交互 this.setState({ isError: true }); } } render() { return (); } }{!this.state.isError ? : 不要奴才給我取名字了!
}
(6) 渲染相關(guān)
render
額...這個不想寫了,先睡覺吧~應(yīng)該寫了這么多個小例子也差不多了~可以動手試試哦!還不清楚的可以 Google 一下,你就知道。
生命周期很重要,其實學(xué)到這里也差不多可以上手寫點項目熟練一下了,其他的更多是思維和編程方面的東西,周期的篇幅多帶帶來一篇吧~其他主題之后再繼續(xù)吧!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/93570.html
摘要:一前言在導(dǎo)讀三中介紹了項目的背景功能需求項目結(jié)構(gòu)以及組件的劃分層次,接下來我們就來看下實際的代碼,這一篇文章會主要分享用到的基礎(chǔ)組件的封裝。 一、前言 在 React 導(dǎo)讀(三) 中介紹了項目的背景、功能需求、項目結(jié)構(gòu)以及組件的劃分層次,接下來我們就來看下實際的代碼,這一篇文章會主要分享用到的基礎(chǔ)組件的封裝。 二、基礎(chǔ)組件設(shè)計 我們在設(shè)計組件之前本來是有一個流程和過程的,這里我寫的組件...
摘要:需要有一定的基礎(chǔ)和的使用經(jīng)驗。這就是屬性的作用。方法接收一個新對象來重新賦值。也接收一個函數(shù),這個回調(diào)函數(shù)這里我默認有一個參數(shù),表示之前的的值,這個函數(shù)的返回值就是最新的。但是不同的是在組件內(nèi)部是只讀的。 前言 寫這篇文章的主要目標(biāo)是讓初學(xué)者更快的上手 React 的項目開發(fā),能有一個循循漸進的理解過程。需要有一定的 JavaScript 基礎(chǔ)和 NPM 的使用經(jīng)驗。不多說了,下面會按...
摘要:場景為了更清晰的安排年前年后的工作和值班,現(xiàn)在要對過年期間人員請假的情況進行統(tǒng)計,并且進行一個簡單的管理。我們現(xiàn)在來訂閱一個名為的事件,用來表示表格中需要展示每條數(shù)據(jù)。 前言 React 導(dǎo)讀(一)React 導(dǎo)讀(二) 在之前 2 篇文章中中學(xué)習(xí)到了寫第一個 Web 組件以及常用的生命周期函數(shù)的使用,這篇文章將繼續(xù)之前的目錄,開始新的知識點補充: [x] React 如何編寫 He...
摘要:最近買了深入理解的書籍來看,為什么學(xué)習(xí)這么久還要買這本書呢主要是看到核心團隊成員及的創(chuàng)造者為本書做了序,作為一個粉絲,還是挺看好這本書能給我?guī)硪粋€新的升華,而且本書的作者也非常厲害。 使用ES6開發(fā)已經(jīng)有1年多了,以前看的是阮一峰老師的ES6教程,也看過MDN文檔的ES6語法介紹。 最近買了《深入理解ES6》的書籍來看,為什么學(xué)習(xí)ES6這么久還要買這本書呢?主要是看到Daniel A...
閱讀 3036·2021-11-18 10:07
閱讀 3785·2021-11-17 17:00
閱讀 2114·2021-11-15 18:01
閱讀 941·2021-10-11 10:58
閱讀 3399·2021-09-10 10:50
閱讀 3471·2021-08-13 15:05
閱讀 1240·2019-08-30 15:53
閱讀 2662·2019-08-29 13:01