React如何創建組件
前言
這節我們將介紹 React 中組件的類別,以及如何創建和使用組件。
本文會向你介紹以下內容:
- 創建類組件
- 創建函數組件
- 渲染組件
- 合成組件
- 提取組件
- Props 是隻讀的
組件介紹
組件(Components) 讓你可以將用戶界面分成獨立的,可復用的小部件,並可以對每個部件進行單獨的設計。
從定義上來說, 組件就像JavaScript的函數。組件可以接收任意輸入(稱為”props”), 並返回 React 元素,用以描述屏幕顯示內容。
Props , 即屬性(Property), 在代碼中寫作 props,故可用 props 指代 properties。
react中有兩種組件:類組件(class components)、函數組件(function components)
創建類組件
類組件的定義有如下要求:
- 類組件需要繼承自 React.Component
- 類組件必須實現render函數
在ES6之前,可以通過create-react-class 模塊來定義類組件,但是目前官網建議我們使用ES6的class類定義。
使用class定義一個組件:
class App extends Component { constructor() { super() this.state = {} } render() { return <h2>Hello App</h2> } }
我們來詳細分析一下類組件有哪幾個部分
- constructor:這是類組件的構造函數,是可選的,我們通常在constructor中初始化一些數據;
- this.state:我們在constructor中給類組件加入state屬性,你可以理解為組件中有一個state對象,其中包含著各種屬性,用於維護組件內部的數據。同時你可以通過this.state.<屬性名>訪問該屬性;
- render(): 該方法是 class 組件中唯一必須實現的方法,類組件通過render()返回組件的顯示內容;
關於 state
我們可以通過this.state給類組件添加數據對象,我們可以通過this.state.<屬性名>去訪問我們setState中的屬性。
constructor(props) { super(props); this.state = { name:"xhs-rookies" } } render(){ return <h2>{this.state.name}</h2> }
但是我們想要修改上述例子中的name屬性的時候,則必須通過react給我們規定好的setState()方法,去給state添加或者修改其中的數值。
this.state.name = 'new xhs-rookies' //錯誤的方式,不允許采用 this.setState({ name: 'new xhs-rookies' }) //正確的方式
簡單點來說,在 react 中頁面是通過數據進行渲染,使用setState()更新的數據,react 會幫我們執行render()去更新頁面,從而將頁面中用到 state 中的數據全部更新。
關於 render
當 render 被調用時,它會檢查 this.props 和 this.state 的變化並返回很多類型,很多時候我們選擇讓該方法返回 React 元素,然後交由 React 去渲染展示:
React 元素:
- 通常通過 JSX 創建。
- 例如,<div/> 會被 React 渲染為 DOM 節點,<MyComponent/> 會被 React 渲染為自定義組件;
- 無論是 <div/> 還是 <MyComponent/> 均為 React 元素。
詳細關於 render() 方法的內容請見React.Component – Render)
創建函數組件
函數組件是使用 function 來進行定義的函數,隻是這個函數會返回和類組件中 render 函數返回一樣的內容。
跟類組件相比,函數組件有自己的特點:
- 沒有生命周期,也會被更新並掛載,但是沒有生命周期函數;
- 沒有 this(組件實例);
- 沒有內部狀態(state);
我們來定義一個函數組件:
export default function App() { return <div>xhs rookies</div> }
渲染組件
在前幾篇中, 我們隻遇到代表 DOM 標簽的 React 元素:
const element = <div />
然而,元素也可以代表用戶定義的組件:
const element = <Welcome name="xhs rookies" />
當 React 遇到一個代表用戶定義組件的元素時,它將 JSX 屬性以一個單獨對象的形式傳遞給相應的組件。 我們將其稱為 “props” 對象。
比如, 以下代碼在頁面上渲染“xhs rookies”:
function Welcome(props) { return <h1>Hello, {props.name}</h1> } const element = <Welcome name="xhs rookies" /> ReactDOM.render(element, document.getElementById('root'))
我們簡單解釋一下上面這個例子:
- 我們調用瞭 ReactDOM.render() 方法並向其中傳入瞭 <Welcome name=”xhs rookies” /> 元素。
- React 調用 Welcome 組件,並向其中傳入瞭 {name: ‘xhs rookies’} 作為 props 對象。
- Welcome 組件返回 <h1>xhs rookies</h1>。
- React DOM 迅速更新 DOM ,使其顯示為 <h1>xhs rookies</h1>。
註意: 組件名稱總是以大寫字母開始。
舉例來說, <div/> 代表一個 DOM 標簽,而 <Welcome/> 則代表一個組件,並且需要在作用域中有一個 Welcome 組件。
你可以深入 JSX閱讀更多關於這點背後的原因。
合成組件
組件可以在它們的輸出中引用其它組件。這使得我們可以使用同樣的組件來抽象到任意層級。一個按鈕,一個表單,一個對話框,一個屏幕:在 React 應用中,所有這些都通常描述為組件。
例如,我們可以創建一個 App 組件,並在其內部多次渲染 Welcome:
function Welcome(props) { return <h1>Hello, {props.name}</h1> } function App() { return ( <div> <Welcome name="rookie-Sara" /> <Welcome name="rookie-Cahal" /> <Welcome name="rookie-Edite" /> </div> ) } ReactDOM.render(<App />, document.getElementById('root'))
通常,新的 React apps 都有一個單獨的頂層 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">{formatDate(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">{formatDate(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">{formatDate(props.date)}</div> </div> ) }
提取組件可能看起來是一個繁瑣的工作,但是在大型的 Apps 中可以回報給我們的是大量的可復用組件。一個好的經驗準則是如果你 UI 的一部分需要用多次 (Button,Panel,Avatar),或者本身足夠復雜(App,FeedStory,Comment),最好的做法是使其成為可復用組件。
Props 是隻讀的
無論你用函數或類的方法來聲明組件, 它都無法修改其自身 props. 思考下列 sum (求和)函數:
function sum(a, b) { return a + b }
這種函數稱為 “純函數” ,因為它們不會試圖改變它們的輸入,並且對於同樣的輸入,始終可以得到相同的結果。
反之, 以下是非純函數, 因為它改變瞭自身的輸入值:
function withdraw(account, amount) { account.total -= amount }
雖然 React 很靈活,但是它有一條嚴格的規則:
註意: 所有 React 組件都必須是純函數,並禁止修改其自身 props 。
當然, 應用 UI 總是動態的,並且隨時有可以改變。
如果我們想要動態改變 UI,那麼就會涉及到我們上面說到的state(狀態) 。我們通過動態的改變state來渲染整個頁面,我們後面會提及,詳情見 深入理解 setState
到此這篇關於React如何創建組件的文章就介紹到這瞭,更多相關React 創建組件內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- React Class組件生命周期及執行順序
- 代碼解析React中setState同步和異步問題
- React如何使用axios請求數據並把數據渲染到組件
- React的三大屬性你都知道嗎
- React setState是異步還是同步原理解析