https://reactjs.org/docs/higher-order-components.html https://codepen.io/gaearon/pen/WooRWa?editors=0010
JSX in Depth
JSX僅支持句法糖syntactic sugar:
React.createElement(component, props, ...children)函數,
JSX code:
<MyButton color="blue" shadowSize={2}>
Click Me </MyButton>
編譯compiles into:
React.createElement(
也可以使用self_closing form of the tag if there are no children. So:
<div className="sidebar" />
compiles into:
函數形式的:
function hello() {
return <div>Hello world!</div>;
}
轉換為:
關於React元素的格式:
React 一定在Scope內。
使用. Dot Notaiton ,可以在JSX中使用點符號。如果一個模塊要調出一些React組件,這樣就方便了。例子:
自定義的組件必須首字母大寫(除非分配它一個首字母大寫的變量)。function Hello(props){...}
在運行時選擇類型Choosing the type at runtime
不能把表達式用做React element type。但是可以把它分配給一個大寫字母的變量,然后就可以間接用JSX格式了
Props in JSX
通過{}, 任何JS expression 都可以作為props. 例如<MyComponent foo={1 + 2 + 3 + 4} />
if statements and for loops 不是JS表達式,不能直接用於JSX。但{}就能用了
條件判斷 Inline的寫法:
{true && expression} //如果是true,則執行表達式。
{condition ? true : false }
防止組件被渲染:
return null; ⚠️,組件的lifecycle 方法鈎子方法,仍然生效componentWillUpdate 和 componentDidUpdate。
Children in JSX
string Literals
<div>This is valid HTML & JSX at the same time.</div>
& 就是&
編譯:
JSX移除一行開頭和結尾的空格
JSX Children
支持內嵌JSX元素作為孩子。在嵌套組件中很有用。
React組件也返回數組元素。return [, ,];
JS expression也可以作為孩子。
//這個是函數作為props.children。
Function as Children
見標黃的代碼.React.createElement(component, props,...child)
Booleans, Null, and Undefined are Ignored.
false ,null, undefined, true都是驗證的孩子,不過它們不渲染。
所以可以作為條件判斷 condition && expression。
如果showHeader是true則渲染<Header />
⚠️ 0會被渲染
如果要讓true渲染使用類型轉換,String()。
Typechecking With PropTypes(未看)
用於檢查輸入的一個方法PropTypes ,這是React內置的方法,JS擴展中也有Flow,TypeScript等擴展插件。
大型的代碼檢查,官方推薦使用Flow or TypeScript 而不是用默認的。
https://reactjs.org/docs/typechecking-with-proptypes.html
PropTypes輸出了一組驗證器用於確保你接收的數據是通過驗證的。如果一個未通過驗證的值提供給一個prop,一條warning會顯示在JS console中。propTypes只用於開發模式。
Refs ans the DOM(未看)
https://reactjs.org/docs/refs-and-the-dom.html
在典型的數據流模式,組件之間的交互使用props。但有少數情況屬於例外情況。
Refs提供了一個方法,能夠使用DOM nodes 和React elements created in the render method。React提供了這個escape hatch逃生艙門。
何時用:
- 管理focus,text selection ,media playback
- 合並第三方DOM庫
- 打開必要的動畫Triggering imperative animations
創建一個ref可以附加到React elements
this.myRef = React.createRef() 並通過ref屬性付給React元素
Uncontrolled Components
推薦使用controlled components 來實現forms, 這時,表格數據被React組件處理。
但我們也可以用別的方式,這時,表格data被DOM自身處理。
既然非控制組件保持了DOM的原生性,有時它比較容易合並React和非React代碼。如果你想要更快並不在乎代碼太臟(可讀性差),也能夠稍微少輸入點代碼。
你應該盡量用可控制的組件。
https://codepen.io/gaearon/pen/WooRWa?editors=0010
紅字是用原生DOM加ref。
Optimizing Performance(略讀)
優化執行的方法和工具。
使用React Developer Tools for Chrome.(也有其他瀏覽器版本)
這個工具可以制作Timeline可視化每個組件mount update, unmount.
Context(一個不使用傳統方法傳遞數據的方法。)
https://reactjs.org/docs/context.html
一整章節,暫時不看。
讓你返回多個元素在一個render()方法中,不需要創建一個額外的DOM 元素。
TheReact.Fragment
component lets you return multiple elements in a
render()
method without creating an additional DOM element:
這時如果是靜態的可以不加key,最好加上。另外用[]也可以,但必須加key
HTML description list:
<dl>
<dt>
<dd></dd>
</dt>
</dl>
Portals
大門,入口。
https://reactjs.org/docs/portals.html
渲染孩子進入一個Dom節點
ReactDOM.createPortal(child,container)
第一個參數是任意的渲染的React child。如an element, string, or fragment.
第二個參數container是一個DOM元素。
一般來說,從一個組件的渲染方法中返回一個元素,它作為孩子附加在離它最近的父節點后。
而使用createPortal這樣就可以插入一個孩子到DOM中不同的位置。 (但仍然受到父組件event事件的影響)
案例:https://codepen.io/gaearon/pen/yzMaBd?editors
Event Bubbling Through Portals
a portal可以插入到在DOM tree的任何位置,不過它在其他方面仍舊是一個普通的React child。
假如:在一個父組件中渲染一個子組件(Modal),那么Modal就可以被這個父組件捕捉到。這個父組件不會考慮Modal是否用了protals。
即便Modal用了protal把代碼插入到不屬於父組件的其他節點,父組件仍然可以捕捉到Modal,父組件定義了一個點擊事件,對Modal中的元素進行點擊也會觸發父組件的點擊事件。
案例:https://codepen.io/chentianwei411/pen/ZoLeBE?editors=0010
Error Boundaries
錯誤邊界。 目的:解決僅僅是部分UI的錯誤就會造成整個app崩潰的問題。
Error boundaries也是一個React組件。JS 錯誤發生在子組件的任何位置,它都可以捕捉到,並且log those errors, 並且display a fallback UI。
Error boundaries 捕捉錯誤是在渲染的時候,因此lifecycle methods 和 constructors of the whole tree都低於Error boundaries.
⚠️以下超出了Error-b的使用范圍:
Event handlers, 異步代碼, 服務器端渲染, 自身拋出錯誤。
Higher-Order Components (基本用法,一些約定沒有看。)
一種代碼的抽象化, 根據dry原則,把有相同邏輯的組件重構。
即重構一個函數,這個函數接受一個組件並return 一個新組件。
要點:發現有很多相同邏輯(內部代碼基本一樣)的組件, 為了減少代碼的量和便於閱讀維護。
https://reactjs.org/docs/higher-order-components.html
// 調用Highter-Order組件withSubscription.把返回的新組件存入一個JSX.
const CommentListWithSubscription = withSubscription(
CommentList,
(DataSource) => DataSource.getComments()
);
function withSubscription(WrappedComponent, selectData) {
//WrappedComponent是組件名字, selectData是數據及其使用的methods。
return class extends React.Component {...} ; //class后面沒有組件名字
}
⚠️ ,不要在higher-order組件中對原有組件修改,如果需要組件進行功能的變化,把這個變化寫在return中。
⚠️, 約定convension: 傳遞不相關的props,通過wrapped 組件。 在render方法中使用不相關的props.
Render Props
術語render prop是一個簡單的技術:在React組件之間,通過使用一個值是函數的prop來分享代碼。
The term "render prop" refers to a simple technique for sharing code between React components using a prop whose value is a function.
一個組件帶着一個render prop,這個組件渲染的時候可以使用這個render prop的值
a render prop is a function prop that a component uses to know what to render.
https://reactjs.org/docs/render-props.html
組件的lifecycle methods
Methods prefixed with will are called right before sth happens. did are called after sth happens.
Mounting
這些方法在一個組件實例被創建和插入DOM時調用。
constructor(props){...} //在加載組件前調用。
before it is mounted,如果組件是一個子類,還需要在其他聲明前面調用super(props)。 constructor()用於初始化state。也用於bind event-handlers to the class instance.
分配給this.state的對象可以包含props。但⚠️這不是時時更新的,最好不這么用,例子:
UNSAFE_componentWillMount() //在加載組件前引用。它在render()前調用。
render()
When called, it should examine this.props
and this.state
and return one of the following types:
- React elements. 包括自定義的組件或原生的DOM component <div />
- String and numbers. 作為text nodes 渲染在DOM中。
- Portals. Created with ReactDOM.createPortal
- null 什么也不加載
- Booleans。一般用於 return test && <Child />模式,當test是true時,加載后面
componentDidMount() //在組件加載后立即引用
用途:
加載遠程endpoint的數據,這里可以實例化network request。
也可以建立任何訂閱並配合componentWillUnmount()取消訂閱。
調用setState(),會激活額外的rendering.
Updating
一個update會被props或state的改變引起。下面的方法當一個組件被再加載時調用。(只看了其中幾個,一共7個方法)
componentWillReceiveProps()
在一個已經加載的組件再次接收新的props之前引用這個方法。 這個方法限制很多不推薦用。
shouldComponentUpdate(nextProps, nextState)
返回true,false。讓React知道一個組件的輸出是否被當前state or propsde 變化所影響。如果是true,則組件再render()。方法默認是true。所以一般不主動使用這個方法。
如果是false,render(), componentWillUpdate(), componentDidUpdate()不會調用。
componentWillUpdate(nextProps, nextSate)
當一個新props or state 被接收到后,在渲染之前引用。
render()
每次更新props or state后,調用render().
componentDidUpdate(prevProps, prevState, snapshot)
在更新發生后,立即引用。
Unmounting
- componentWillUnmount(): 在一個組件被卸載和刪除前立即引用。用於執行必要的清潔。如未驗證的timers, 取消網絡請求, 清潔任何在componentDidMount()中的訂閱
- componentDidCatch():這個方法被調用當一個❌發生在渲染中,在lifecyle方法中,或者在一個孩子組件的constructor中。
Other APIS
setState()
enqueuqs changes to the component state and tells React that this component and its children need to be re-rendered with the updated state.
改變組件的狀態state並告訴React“組件和它的孩子需要根據更新的state再渲染”
這是一個主要的方法,用來更新user interface in response,事件處理和服務器響應。
把setState()當作一個request,而不是更新組件的即時命令。
setState()不總是立即執行更新組件,因為它類似request,有延遲。因此,使用componentDidUpdate或者setState(updater, callback)可以保證fire(立即執行).
setState(updater, callback)
updater是一個函數:(prevState, props) => stateChange //prevState是之前state的一個引用。 例子:用props.step增加一個值到state中。
callback參數是可選的函數。在setState完成更新,組件被再渲染后執行這個函數,推薦使用componentDidUpdate代替。
第一個參數可以是一個對象object.代替一個函數。 這個執行會把狀態變化合並到新狀態中。
this.setState({quantity: 2})
forceUpdate()
component.forceUpdate(callback),如果render()方法依靠其他數據源,你可以告訴組件調用forceUpdate()來再渲染。個人理解:這個方法就是用來執行渲染的。
Class Properties
defaultProps
給組件的property設定默認值。
渲染的時候自動增加上color="blue"
displayName
https://reactjs.org/docs/higher-order-components.html#convention-wrap-the-display-name-for-easy-debugging
debug用。
Instance Properties
- props
- state
ReactDOM
import ReactDOM from 'react-dom'
react-dom package提供了DOM-specific methods。大多數組件不需要使用這個module.
ReactDOM.render(element, container[, callback])
渲染一個React element到DOM中。具體位置是container, 返回a reference 給組件。
如果之前已經渲染進container中,更新時只修改必要的部分。
callback可選,在組件渲染或更新后執行.\
createPoratal()
ReactDOM.createPortal(child, container)
hydrate()
unmountComponentAtNode()
findDOMNode()
ReactDOMServe
import ReactDOMServer from 'react-dom/server';
用於把組件渲染到靜態標記中,一般用於一個Node server
這兩個方法可以用於server,也可以用在瀏覽器。
renderToString()
renderToStaticMarkup()
ReactDOMServer.renderToString(element)
渲染一個React元素到 原始HTml. React返回一個HTML string。
DOM Elements
https://reactjs.org/docs/dom-elements.html
style
style屬性可以接受JS 對象。屬性要用駝峰寫法。如backgroundImage. px可以省略
value
<input>, <textarea>組件支持value屬性。
className
用來指定css class的名字。
checked
<input>組件中的type類型為checkbox or radio的支持這個屬性。
All Supported HTML Attributes
SyntheticEvent
人工事件
event handlers被傳到人工事件的實例,一個跨瀏覽器的包裹器(包含瀏覽器的原生事件)。
每個SyntheticEvent對象有一系列的屬性attributes:如:
currentTarget, target, type, timeStamp, isTrusted, preventDefault()等等。
https://reactjs.org/docs/events.html