React元件中對子元件children進行加強
問題
如何對元件的children進行加強,如:新增屬性、繫結事件,而不是使用<div>{this.props.children}</div>
在<div>
上進行處理。
前車之鑑
今天寫元件遇到這個問題,在網上查閱了很多資料,都說可以使用React.cloneElement
進行處理,但是結果並不是預期想要的。
先看看這個東西有什麼用:
React.cloneElement(element, [props], [...childrn])
根據React官網的說法,以上程式碼等價於:
<element.type {...element.props} {...props}>{children}</element.type>
這麼做其實也是給children
包了一層標籤,再對其進行間接處理,沒有直接修改children
。
如:
// App.jsx
<Father>
<div style={{ color: 'red' }} onClick={() => console.log('hello')}>
demo
</div>
<Father>
我們希望在Father.jsx
的內部將div
轉為inline-block
。按照網上的做法,是這樣的:
// Father.jsx
const Son = React.cloneElement(
this.props.children,
{
style: {
display: 'inline-block'
}
}
)
但是實際效果是這樣的:
<div style={{ dispaly: 'inline-block' }}>
<div style={{ color: 'red' }} onClick={() => console.log('hello')}>
demo
</div>
<div>
哈!?子元素的父元素被設為了inline-block
,和我們想要的<div>demo</div>
被設為inline-block
。結果與預期完全不同,簡直大失所望!!!
React.clone
根本對不起它clone
的名字!!!
自我探索
思路: jsx語法表示的元素只是react元件的一個語法糖。所以元件是物件。既然是物件我們就可以直接對其進行修改。
嘗試在控制檯列印一個如下react元件:
// this.props.children
console.log(
<div
style={{ color: 'red' }}
onClick={() => {
console.log('hello');
}}
>
demo
</div>
);
如下:
所以直接修改this.props.children
即可:
// Father.jsx
const { children } = this.props;
const Son = {
...children,
props: {
...children.props,
dispaly: {
...children.style,
display: 'inline-block'
},
onTransitionEnd: () => { console.log('hello world') }
}
}
總結
如何對元件的children進行直接加強,直接修改this.props.children
物件即可。