基本使用方法(v16.0.x)
核心語法
JSX : 形如HTML和Javascript的組合,是一種 JavaScript 的語法擴充套件。 JSX有如同HTML一般的寫法,符合你的寫作習慣,表示式需要包含在大括號裡。
Hello, {formatName(user)}!
複製程式碼
JSX 的特性更接近 JavaScript 而不是 HTML , 所以 React DOM 使用 camelCase 小駝峰命名 來定義屬性的名稱,而不是使用 HTML 的屬性名稱。
JSX 允許直接在模板插入 JavaScript 變數。如果這個變數是一個陣列,則會展開這個陣列的所有成員。
虛擬DOM的特點:
React is going to use virtual DOM to try to find the minimum number of steps to go from the previous render to the next. React核心diff演算法比較Dom樹的最小化差異, 只重新渲染髮生變化的Dom樹區域性, 提高渲染效率。
JSX 代表 Objects
Babel 轉譯器會把 JSX 轉換成一個名為 React.createElement() 的方法呼叫。
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
複製程式碼
執行效果同下:
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
複製程式碼
元素渲染
如上,元素事實上只是構成元件的一個部分。通過ReactDom.render()方法來將元素渲染到頁面上。 技巧:將介面視為一個個特定時刻的固定內容(就像一幀一幀的動畫),而不是隨時處於變化之中(而不是處於變化中的一整段動畫)將會有利於我們理清開發思路,減少各種bugs。 class Demo extends React.Component {} 方法用於生成一個繼承自React的衍生元件。
元件
定義:元件從概念上看就像是函式,它可以接收任意的輸入值(稱之為“props”),並返回一個需要在頁面上展示的React元素。
定義一個元件最簡單的方式是使用JavaScript函式:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
複製程式碼
元件類的第一個字母必須大寫,只能有一個頂層標籤。 所有元件類都必須有自己的render方法,用於輸出元件。
Props
所有的React元件必須像純函式那樣使用它們的props,無法對Props進行寫操作。 class屬性需要寫成className,for屬性需要寫成htmlFor。 this.props 作為元件的資料入口,而 this.state 是運轉於元件內部的流通資料。 react的單項資料流,以props作為元件注入口,實現元件間的通訊入口,從父元件到子元件的單向注入。
React元件生命週期(常用)
componentDidMount: 元件掛載完成後
componentWillReceiveProps:元件props發生變化(深層次變化存在檢測不到的清空)
shouldComponentUpdate: 效能優化點,設定返回值為false,在不需要是阻止元件重新渲染。
React 理念
React的眾多優點之一是它讓你在編寫程式碼的時候同時也在思考你的應用。
構建一個應用的基本思路:
- 第一步:把 UI 劃分出元件層級
UI 和資料模型往往遵循著相同的資訊架構,這意味著將 UI 劃分成元件的工作往往是很容易的。只要把它劃分成能準確表示你資料模型的一部分的元件就可以。 - 第二步:用 React 建立一個靜態版本
現在有了元件層級,是時候去實現你的應用了。最簡單的方式是先建立一個靜態版本:傳入資料模型,渲染 UI 但沒有任何互動。在較為簡單的例子中,通常自頂向下更容易,而在較大的專案中,自底向上會更容易並且在你構建的時候有利於編寫測試。 - 第三步:定義 UI 狀態的最小(但完整)表示 為了正確構建你的應用,首先你需要考慮你的應用所需要的最小可變狀態集。要點是 DRY:不要重複(Don’t Repeat Yourself)。找出應用程式的絕對最小表示並計算你所需要的其他任何請求。例如,如果你正在建立一個 TODO 列表,只要儲存一個包含 TODO 事項的陣列;不要為計數保留一個單獨的狀態變數。相反,當你想要渲染 TODO 計數時,只需要使用 TODO 陣列的長度就可以了。
- 第四步:確定你的 State 應該位於哪裡 React 中的資料流是單向的,並在元件層次結構中向下傳遞。確定應用state的最小集合,提升至所有元件的更高父元件。
- 第五步:新增反向資料流 向底層元件傳入所需的資料控制器,讓其具備修改頂層資料的能力。
高階用法
- this.props.children 屬性,它表示元件的所有子節點,props.children 可以像其它屬性一樣傳遞任何資料,而不僅僅是 React 元素(字串,陣列,react元素)。
- 元件類的PropTypes屬性,用來驗證元件的輸入props屬性是否符合要求。用於規範元件輸入。(V15.5+ 使用 prop-types 庫)
propTypes: {
title: React.PropTypes.string.isRequired,
}
複製程式碼
- 有時需要從元件獲取真實 DOM 的節點,這時就要用到 ref 屬性。ref可以獲取到虛擬Dom對應的真實Dom節點。
- 當元件更新時,例項仍保持一致,狀態得以在渲染之間保留。React通過更新底層元件例項的props來產生新元素(字串,react元素),並在底層例項上依次呼叫componentWillReceiveProps() 和 componentWillUpdate() 方法
- React 中一個常見模式是為一個元件返回多個元素。Fragments 可以讓你聚合一個子元素列表,並且不在DOM中增加額外節點。形如:<></>
Portals
ReactDOM.createPortal(child, container)
複製程式碼
Portals 提供了一種很好的將子節點渲染到父元件以外的 DOM 節點的方式。
應用:對於 portal 的一個典型用例是當父元件有 overflow: hidden 或 z-index 樣式,但你需要子元件能夠在視覺上“跳出(break out)”其容器。例如,對話方塊、hovercards以及提示框。(如antd中Select,Dropdown,Modal等元件的實現)
Error Boundaries 錯誤邊界
目的:用於捕獲其子元件樹 JavaScript 異常,記錄錯誤並展示一個回退的UI的React元件,避免因區域性錯誤導致整個元件樹的異常。 標誌: 如果一個類元件定義了一個名為 componentDidCatch(error, info) 的新方法,則其成為一個錯誤邊界
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
// Display fallback UI
this.setState({ hasError: true });
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
複製程式碼
而後可以像一個普通的元件一樣使用:
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
複製程式碼
高階元件
將邏輯相似或共通的元件抽離出來,從容器層向內注入差異化資料模型。高階元件是通過將原元件包裹在容器元件裡面的方式來組合使用原元件。高階元件就是一個沒有副作用的純函式。為統一邏輯的內層元件提供資料入口,並返回一個定製化類似元件。(如Redex中的connect)