1.1 正常dom元素express
<Grid>
<Row />
<Row />
<Row />
</Grid>
class Grid extends React.Component {
render() {
return <div>{this.props.children}</div>
}
}複製代碼
1.2 函數
api
<Executioner>
{(arg) => <h1>Hello World!</h1>}
</Executioner>
class Executioner extends React.Component {
render() {
// See how we're calling the child as a function? // ↓ return this.props.children(arg) //由於children是函數,因此這裏確定也能夠傳參 } }複製代碼
不僅如此,children還能夠是jsx等等數組
2.1 React.Children.mapbash
<Executioner>
{(arg) => <h1>Hello World!</h1>}
</Executioner>
class Executioner extends React.Component {
render() {
// See how we're calling the child as a function? // ↓ return this.props.children(arg) //由於children是函數,因此這裏確定也能夠傳參 } }複製代碼
像上圖咱們能夠用this.props.children操做,好比咱們當咱們傳了多個子組件以後又要怎麼渲染出來呢數據結構
<IgnoreFirstChild>
<h1>First</h1>
<h1>Second</h1> // <- Only this is rendered
</IgnoreFirstChild>
class IgnoreFirstChild extends React.Component {
render() {
const children = this.props.children
return (
<div>
{this.props.children.map((child, i) => {
// Ignore the first child
if (i < 1) return
return child
})}
// 這裏咱們用了this.props.children.map,而且忽略到第一個元素,可是若是這裏傳進來的是上面
例子是上圖中的函數,這裏就會報錯,由於map,使用React.Children.map則不會報錯
{React.Children.map(children, (child, i) => { // Ignore the first child
if (i < 1) return
return child
})}
// 這裏咱們用了React.Children.map,這是React提供的一些幫助函數
</div>
)
}
}複製代碼
因此使用React.Children.map就沒有問題了,這是一種更加穩妥的方式app
<IgnoreFirstChild>
{() => <h1>First</h1>} // <- Ignored 💪
</IgnoreFirstChild>
//使用this.props.children會報錯,用React.Children.map不會報錯
複製代碼
2.2 React.Children.countdom
class ChildrenCounter extends React.Component {
render() {
return <p>React.Children.count(this.props.children)</p>
}
}複製代碼
// Renders "1"
<ChildrenCounter>
Second!
</ChildrenCounter>
// Renders "2"
<ChildrenCounter>
<p>First</p>
<ChildComponent />
</ChildrenCounter>
// Renders "3"
<ChildrenCounter>
{() => <h1>First!</h1>}
Second!
<p>Third!</p>
</ChildrenCounter>
// 每次都精準算出了子組件的個數複製代碼
2.3 React.Children.toArray
函數
當你須要把子組件轉化成數組時,能夠使用toArray這個函數ui
class Sort extends React.Component {
render() {
const children = React.Children.toArray(this.props.children)
// Sort and render the children
return <p>{children.sort().join('')}</p>
}
}
<Sort>
// We use expression containers to make sure our strings
// are passed as three children, not as one string
{'bananas'}{'oranges'}{'apples'}
</Sort>
//輸出 apples bananas oranges
<Sort>
// We use expression containers to make sure our strings
// are passed as three children, not as one string
我是內容
</Sort>
//這樣子也並不會報錯複製代碼
2.4 React.Children.only
this
若是你但願傳進來的組件只是一個,並且是個函數
咱們先借用proppropTypes來實現
class Executioner extends React.Component {
render() {
return this.props.children()
}
}
Executioner.propTypes = {
children: React.PropTypes.func.isRequired,
}
//這樣就會在console裏打印出日誌來,可是有的時候開發者很容易忽略這些消息。這個時候咱們就應該在render方
法里加入React.Children.only。
複製代碼
class Executioner extends React.Component {
render() {
return React.Children.only(this.props.children)()
}
}
//若是子組件多於一個會拋出一個錯誤,整個app會中止--絕對不會讓一些偷懶的開發搞亂咱們的組件。
複製代碼
2.5 React.cloneElement
好比咱們有一個RadioGroup組件,該組件包含一些RadioButton子組件(最終渲染成<input type="radio"> )。
RadioButtons不是由RadioGroup渲染的,它們做爲子組件傳入,這意味着咱們的代碼看起來像這樣:
render() {
return(
<RadioGroup>
<RadioButton value="first">First</RadioButton>
<RadioButton value="second">Second</RadioButton>
<RadioButton value="third">Third</RadioButton>
</RadioGroup>
)
}複製代碼
可是這樣子的話RadioButton不會出如今一個RadioGroup中,因此咱們必須給全部的RadioButton加上同一個屬性name
<RadioGroup>
<RadioButton name="g1" value="first">First</RadioButton>
<RadioButton name="g1" value="second">Second</RadioButton>
<RadioButton name="g1" value="third">Third</RadioButton>
</RadioGroup>
//這種方法顯然能夠,可是有點笨複製代碼
咱們能夠先用React.children改寫一下
class RadioGroup extends React.Component {
constructor() {
super()
// Bind the method to the component context
this.renderChildren = this.renderChildren.bind(this)
}
renderChildren() {
return React.Children.map(this.props.children, child => {
// TODO: Change the name prop to this.props.name
return child
})
}
render() {
return (
<div className="group">
{this.renderChildren()}
</div>
)
}
}
//這裏問題就是咱們仍是沒有給每一個RadioButton加上property name
複製代碼
這裏咱們用上咱們最後的一個api React.cloneElement
const cloned = React.cloneElement(element, {
new: 'yes!'
})
第一個參數是拷貝源的React element, 第二個參數是prop object,clone之後會把這個prop object設置成屬
性給拷貝結果。cloned元素將持有名爲new的屬性,屬性值爲"yes!"複製代碼
那麼這裏咱們就來改寫上面的代碼
class RadioGroup extends React.Component {
constructor() {
super()
// Bind the method to the component context
this.renderChildren = this.renderChildren.bind(this)
}
renderChildren() {
return React.Children.map(this.props.children, child => {
return React.cloneElement(child,
name: this.props.name
})
})
}
render() {
return (
<div className="group">
{this.renderChildren()}
</div>
)
}
}
<RadioGroup name="g1">
<RadioButton value="first">First</RadioButton>
<RadioButton value="second">Second</RadioButton>
<RadioButton value="third">Third</RadioButton>
</RadioGroup>
//這樣子只須要寫個一個name即可以實現功能複製代碼