react-元件vs繼承
React有十分強大的組合模式,我們推薦組合而非繼承來實現元件之間的程式碼重用
包含關係
有些元件無法提前知道他們子元件的具體內容,在SlideBar(側邊欄)和Dialog(對話方塊)等展現通用容器的特別容易遇到這樣的情況
我們建議這些元件使用children prop
來將他們的子元件渲染到結果中
props.children
把所有子元件顯示出來
示例
import React ,{Component} from 'react' import './combanation.css' function FancyBorder (props) { return( <div className={'FancyBorder FancyBorder-' + props.color}> {props.children} </div> ) } function WelcomeDialog () { return ( <FancyBorder color='blue'> <h1 className='Dialog-title'>Welcome</h1> <p className='Dialog-message'>Thank you visition our spacecraft</p> </FancyBorder> ) } export default WelcomeDialog
上面程式碼中,通過props.children,我們可以把FancyBorder
裡面的所有內容作為引數傳遞給FancyBorder元件,因為FancyBorder
將{props.children}
渲染在一個div
中,被傳遞的這些紙元件最終都會出現在輸出結果中
少數情況下,你可能需要在一個元件中預留幾個'洞',這種情況下,我們可以不適用children
,而是自行約定:將所有內容傳入props,並使用相應的prop
示例
function SplitPane (props) { return( <div className='SplitPane'> <div className='SplitPane-left'>{props.left}</div> <div className='SplitPane-right'>{props.right}</div> </div> ) } function Contacts(){ return( <ul> <li>微信</li> <li>電話</li> <li>QQ</li> </ul> ) } function Chat(){ return( <div>請和我聯絡</div> ) } function Bar(){ return ( <SplitPane left={<Contacts />} right={<Chat />}></SplitPane> ) } export default Bar
<Contacts />
和<Chat />
之類的React元素本質就是物件,所以可以把它們當做props,像其他資料一樣傳遞,這種方法可能使你想到其他庫的槽(slot)的概念,但在react中沒有
特例關係
有些時候,我們會把一些元件看成是其他元件的特殊例項,比如WelcomeDialog
是Dialog
的特殊例項
在React中,我們也可以通過組合來實現這一點,"特殊"元件可以通過props定製並渲染一般元件
function Dialog (props) { return( <FancyBorder color='blue'> <h1>{props.title}</h1> <p>{props.message}</p> </FancyBorder> ) } function WelcomeDialog(){ return( <Dialog title='Welcome' message='Thank you for visiting our spacecraft'></Dialog> ) }
組合也同樣適用於class形式定義的元件
示例
function Dialog (props) {
return(
<FancyBorder color='blue'>
<h1>{props.title}</h1>
<p>{props.message}</p>
{props.children}
</FancyBorder>
)
}
class SigUpDialog extends React.Component{
constructor (props) {
super(props);
console.log(this)
this.state = {
login:''
}
}
render () {
return(
<Dialog title='Mars Exploration Program' message='How should we refer to you'>
<input type="text" value={this.state.login} onChange={this.handleChange.bind(this)} />
<button onClick={this.handleSignUp.bind(this)}>sign me up</button>
</Dialog>
)
}
handleChange(e){
this.setState({
login:e.target.value
})
}
handleSignUp(){
alert(`Welcome aboard,${this.state.login}!`)
}
}
export default SigUpDialog
那麼繼承呢?
在Facebook,成百上千個元件中適用react,並沒有發現需要使用繼承來構建元件層次的情況
props和組合為你提供了清晰而安全地定製元件外觀和行為的靈活方式注意:元件可以接受任意 props,包括基本資料型別,React 元素以及函式。
如果你想要在元件間複用非 UI 的功能,我們建議將其提取為一個單獨的 JavaScript 模組,如函式、物件或者類。元件可以直接引入(import)而無需通過 extend 繼承它們。