1. 程式人生 > >React.js學習知識小結(一)

React.js學習知識小結(一)

知識 學習 瀏覽器兼容 防止 阻止 渲染 開頭 鼠標事件 幫我

學習React也有半個月了吧,這裏對所學的基礎知識做個簡單的總結。自己先是跟著官方文檔學,差不多學了四五天,也跟著入門教程做了一個簡單的小栗子。然後跟著阮一峰老師的教程上手了幾個小Demo,後來在網上發現了一本很好的書React.js小書,自己斷斷續續也學了幾天,上面也幾個實戰的小項目,可以跟著練練手。
話不多說,就直接來總結吧!

  • JSX
  • 組件
  • 區分props和state
  • 生命周期函數
  • 事件系統
  • 高階組件
  • React.js的context
  • 函數式編程
  • 使用PropTypes檢查類型
  • ref屬性和React.js中的DOM操作

JSX


JSX其實是一個表達式,但是經過編譯之後,JSX表達式會成為常規的JavaScript對象,可以在JSX中嵌入任何的JavaScript表達式,方法是放在花括號裏面,還可以將JavaScript表達式嵌入到HTML的屬性當中,還有HTML屬性也是使用駝峰式命名的方法。
註意

:這裏JSX防止註射攻擊,React DOM會在渲染之前將嵌入在JSX中的任何值進行轉義,在呈現之前,全部轉換成字符串。
這裏引出兩個個關於面試的問題?

  1. 怎麽將一個類似HTML的JSX結構轉換成一個JavaScript對象
  2. 為什麽不直接通過JSX到達DOM元素呢,而是要通過JSX-JavaScript對象-DOM元素-插入頁面。
    針對第一個問題,需要先了解JSX的原理問題,其實JSX就是JavaScript對象,其實每個DOM元素的結構都可以用JavaScript對象來表示,一個DOM元素包含的信息其實只有三個:標簽名、屬性、子元素。
{
    tag: ‘div‘, 
    attrs: { className: ‘box‘, id: ‘content‘}, 
    children: [
                         { tag: ‘div‘, arrts: { className: ‘title‘ }, children: [‘Hello‘] },
                       { tag: ‘button‘, attrs: null, children: [‘Click‘] }
] 
}

我也只是想到一個笨的方法思路,既然想將一個類似HTML的結構的JSX轉換成一個JavaScript對象,自然而然需要一個中間者,而這個中間者可以是一個函數,通過傳入參數,然後返回一個JavaScript對象,這個參數可以通過傳統的DOM操作來獲取這個JavaScript對象所需要的tag,attrs,children。

針對第二個問題,有兩個原因:
第一個:當我們拿到一個表示UI結構和信息的對象的時候,不一定會把元素渲染到瀏覽器的普通頁面上,這個是通過react-dom實現的,也有可能將這樣的對象渲染到canvas,渲染成一個APP.
第二個:當數據要變化的時候,需要更新組件的時候,可以用比較快的算法來操作JavaScript對象,而不用直接操作頁面上的DOM,這樣就可以減少瀏覽器重排,極大的優化性能。

組件

說到組件問題,就有幾個小點需要提出來

  • 怎麽劃分組件
    -有狀態組件和無狀態組件
  • 組件的組合和繼承
    -組合組件相當於構建了一個組件樹
  • 編寫組件時需註意的規範
    1.組件的私有方法都是以_開頭,所有事件監聽的方法都用handle開頭,把事件監聽方法傳給組件的時候,屬性名用on開頭
    2.組件內容的編寫順序:
    (1)static開頭的類屬性,如defaultProps,propTypes
    (2)構造函數,constructor
    (3)getter和setter
    (4)組件的生命周期
    (5)_開頭的私有方法
    (6)事件監聽的方法
    (7)render開頭的方法,有時候render方法裏面的內容會分開到不同函數裏面進行,這些函數都以render開頭
    (8)render方法

區分props和state

React元素可以是DOM標簽,也可以是用戶自定義組件,在涉及到組件渲染的時候,就需要用到自定義組件,當React元素遇到的是用戶自定義組件,它會將JSX屬性當作單個屬性傳遞給該組件,這個對象稱之為props。

對於state,要實時更新UI是通過某個組件內部的方法,從而實現封裝的效果。狀態和屬性十分相似,但是狀態是私有的,完全受控於當前組件,用ES6的類的語法定義組件,有一些特性,局部狀態就是如此。

使用類class定義組件,就可以使用類的一些特性:局部狀態和生命周期鉤子。而且不能直接更新狀態,而是使用setState()方法,而且初始化this.state的方法只能是構造函數裏面。

組件可以選擇將狀態作為屬性傳遞給其子組件,這個通常被稱為自頂向下或單向數據流。可以在有狀態的組件中使用無狀態組件,也可以在無狀態組件中使用有狀態組件。

盡量少的使用state,盡量多的使用props。

生命周期函數

組件的生命周期可以分成3個狀態:
Mounting:已插入真實DOM,
updating:正在被重新渲染,
Unmounting:已移出真實DOM.
上面的三種狀態又存在兩種:will和did,所以總共來說有6種方法。


1.Mounting狀態下的方法調用順序:

->getDefaultProps():對於每個組件來講,這個方法只會調用一次,該組件類的所有後續應用,getDefaultProps將不會再被調用,其返回的對象可以用於設置默認的props值
->getInitialState():在組件實例化之前被調用一次,返回初識的state值,有狀態組件應該實現此函數。對於組件的每個實例來說,這個方法的調用有且只有一次,用來初識話每個實例的state,在這個方法裏面可以訪問組件的props,每一個React組件都有自己的state,與props的區別在於state只位於組件的內部,而props在所有實例中共享。
->componentWillMount():在組件掛載之前調用一次
->render()
->componentDidMount():在組件掛載之後調用一次

2.每次修改state,都會重新渲染組件,會依次調用下列方法
shouldComponenrtUpdate()
componentWillUpdate()
render()
componentDidUpdate()


3.Updating狀態下的順序
父組件render()
->componentWillReceiveProps:組件的props屬性可以通過父組件來更改,此時這個方法將被調用。可以在這個方法裏更新state,以觸發render重新渲染組件。
->shouldComponentUpdate():可以返回flase阻止組件的重新渲染,從而提高性能
->componentWillUpdate()
->render()
->componentDidUpdate():除了首次render之後調用componentDidMount,其他render結束之後都調用這個方法


4.Unmounting
每當React使用完一個組件,這個組件必須從DOM中卸載後被銷毀,此時
componentWillUnmount會被執行,完成所有的清理和銷毀工作。在componentDidMount中添加的任務都需要在該方法中撤銷,如創建的定時器或時間監聽器。

事件系統

在React.js中不需要手動調用瀏覽器原生的addEventListener進行事件監聽,它幫我們封裝好了一系列的on事件,而且不需要考慮不同瀏覽器的兼容性。這些事件的屬性都要用駝峰命名法。這些on事件監聽只能用在普通的HTML標簽上,而不能用在組件標簽上。

和普通瀏覽器一樣,事件監聽函數會自動傳入一個event對象,這個對象和普通的瀏覽器event對象所包含的方法和屬性都基本一致,不同的是React.js這個event對象不是瀏覽器提供的,而是它自己內部構建的。React.js將瀏覽器原生的event對象進行了封裝,不用考慮瀏覽器兼容問題。

Function.prototype.bind,調用f.bind(someObject)會創建一個和f有著相同函數體和作用域的函數,但是這個新函數中,this將永遠被綁定在bind的第一個參數,無論這個函數是如何被調用的。React.js的事件監聽方法需要手動bind到當前實例,這種模式在React.js中是非常常用的

事件分個簡單的小類:

  • 剪貼板事件
  • 鍵盤事件
  • 鼠標事件
  • 觸摸事件
  • 焦點事件
  • 表單事件
  • UI事件

React.js學習知識小結(一)