組件使 UI 分離爲獨立可服用的塊,可隔離思考每個塊。這頁介紹組件理念。在此查閱 組件 API 參考。javascript
概念上講,組件與 JavaScript 函數相像。他們接受任意輸入(稱爲 "props") 而後返回描述屏幕上顯示的 React elements 。html
定義一個組件最簡單的方式是寫一個 JavaScript 函數:java
function Welcome(props) { return <h1>Hello, {props.name}</h1>; }
這個函數是一個有效的 React component 由於它接受了單一的 "props"(這個是 properties 的縮寫)對象數據參數且返回了一個 React element. 咱們稱這樣的組件爲 "functional" 由於他們就是 JavaScript functions 的字面含義。react
也可使用 ES6 class 來定義一個組件:api
class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } }
以上兩種組件對 React 來講沒有區別。數組
classes 有額外的特色咱們[下一部分]()討論。在那以前,簡明旗艦咱們使用函數組件。網絡
以前,咱們只鼓勵 React elements 呈現 DOM 標籤:函數
const element = <div />;
然而, elements 也能呈現自定義組件:網站
const element = <Welcome name="Sara" />;
當 React 發現一個 element 呈現用戶自定義組件,它會將 JSX 屬性作爲單個對象傳遞到這個組件。 咱們稱這個對象 "props".this
例如: 這個代碼在頁面渲染出 "Hello, Sara":
function Welcome(props) { return <h1>Hello, {props.name}</h1>; }
扼要重述例子中發生了什麼:
Note: 組件命名以大寫字母開頭。
React 將小寫開頭的組件當作 DOM 標籤處理。例如, <div /> 表示一個 HTML div 標籤, 可是 <Welcome /> 表示一個組件並且須要 Welcome 在其以內。
組件能夠指它們輸出中的其餘組件。這使得能夠在任意細節層級使用一樣的組件。 按鈕、表單、對話框、屏幕:在 React 應用,以上這些都統稱爲組件。
例如,能夠建立一個 App 組件屢次渲染 Welcome:
function Welcome(props) { return <h1>Hello, {props.name}</h1>; } function App() { return ( <div> <Welcome name="Sara" /> <Welcome name="Cahal" /> <Welcome name="Edite" /> </div> ); } ReactDOM.render( <App />, document.getElementById('root') );
典型的,新 React 應用有單獨一個 App 組件在最外層。然而整合 React 到一個已有的應用,你應該從一個相似 Button 的小組件開始, 漸漸擴展到最上層視圖層級。
不要懼怕吧組件粉等更小的組件。
例如, 思考 Comment 組件:
function Comment(props) { return ( <div className="Comment"> <div className="UserInfo"> <img className="Avatar" src={props.author.avatarUrl} alt={props.author.name} /> <div className="UserInfo-name"> {props.author.name} </div> </div> <div className="Comment-text"> {props.text} </div> <div className="Comment-date"> {formateDate(props.date)} </div> </div> ); }
組件接受 author(對象), text(字符串)和 date(日期) 做爲 props, 描繪一個 評論界面到社交網站上。
這個組件修改須要技巧由於全部嵌套很難複用獨立的部分。咱們從中提取一些組件出來。
第一步咱們提取 Avatar:
function Avatar(props) { return ( <img className="Avatar" src={props.user.avatarUrl} alt={props.user.name} /> ); }
Avatar 不須要知道它被渲染在一個 Comment中。這是爲何咱們給它的 prop 取一個通用的名字: user 而不是 author.
咱們建議爲組件 props 命名從組件自身角度出發,而不是內容在哪裏使用。
咱們還能夠簡化 Comment 一點:
function Comment(props) { return ( <div className="Comment"> <div className="UserInfo"> <Avatar user={props.author} /> <div className="UserInfo-name"> {props.author.name} </div> </div> <div className="Comment-text"> {props.text} </div> <div className="Comment-date"> {formateDate(props.date)} </div> </div> ); }
接下來,我麼提取一個 UserInfo 組件緊鄰用戶的名稱來渲染 Avatar :
function UserInfo(props) { return ( <div className="UserInfo"> <Avatar user={props.user} /> <div className="UserInfo-name"> {props.user.name} </div> </div> ); }
更近一步簡化 Comment :
function Comment(props) { return ( <div className="Comment"> <UserInfo user={props.author} /> <div className="Comment-text"> {props.text} </div> <div className="Comment-date"> {formateDate(props.date)} </div> </div> ); }
提取組件看起來枯燥無味,可是一版可複用組件在一個較大的應用中回報豐厚。
好的標準是一部分你的 UI 被屢次應用(Button, Panel, Avatar), 或者它足夠複雜(App, FeedStory, Comment), 成爲一個可複用的組件是個好的選擇。
不論你以函數仍是類的方式聲明一個組件,它必須從不修改它的 props. 思考許下 sum 函數:
function sum(a, b) { return a + b; }
相似的函數被成爲 "pure(純)" ,由於他們不嘗試修改他們的輸入,並且他們根據相同的輸入返回相同的輸出。
相反, 下面這個函數就不是純函數,由於它修改了本身的入參。
function withdraw(account, amount) { account.total -= amount; }
React 至關靈活可是它有一個嚴格的規則:
全部 React 組件必須想一個純函數同樣對待它們的 props.
固然, 應用 UI 隨時間動態改變。下一部分,介紹一個新概念 "state".
State 使得 React 組件能夠在響應用戶行爲,網絡請求或任何東西時隨時間變化改變它們的輸出,卻不破壞這條規則。
我有點分不清楚到底應該嚴格要求本身擠時間作,仍是隨意些。這個問題得好好思考一下。