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