最近項目中使用redux-form趕上性能瓶頸,react
須要100行以上聯動表單變得極其卡git
Field 使用 PureComponent 減小沒必要要的渲染[若是無效用shouldComponentUpdate ]github
推薦使用shouldComponentUpdate 精確控制到每行及每一個輸入框的渲染redux
覆蓋掉redux-from的onChange事件 改用onFocus和onBlurbash
下面代碼我在FormMembers裏遍歷了fields,因此FormMembers從新渲染時會致使fields所有從新渲染。性能
優化後使用shouldComponentUpdate控制到每一行及每個輸入框的從新渲染,提升了很是多的性能!優化
優化前代碼及結構ui
//表單
class Form extends Component{
render() {
return (
<div>
<form onSubmit={()=>{}}>
<table className="recipe_table" >
<FieldArray
name="members"
recipeName="herbal"
component={FormMembers}
change={change}
public_expense={public_expense}
/>
</table>
</form>
</div>)
}
}
//Members
class FormMembers extends Component{
render() {
let {fields}=this.props;
return(
<tbody>
{fields.map((item,key)=>{
console.log('//此處省略大量計算')
return (
<tr key={key} >
<td>
<Field name={`${item}.name`} component={Field}/>
</td>
</tr>
)
})}
</tbody>)
}
}
//數字輸入框
class Field extends Component{
render(){
let {input}=this.props;
return <input {...input} />
}
}
複製代碼
優化後this
import isEqual from "lodash/isEqual";
//表單
class Form extends Component{
render() {
return (
<div>
<form onSubmit={()=>{}}>
<table className="recipe_table" >
<FieldArray
name="members"
recipeName="herbal"
component={FormMembers}
change={change}
public_expense={public_expense}
/>
</table>
</form>
</div>)
}
}
//Members
class FormMembers extends Component{
render() {
let {fields}=this.props;
return(
<tbody>
{fields.map((item,key)=>(<Line item={item} lineKey={key} />))}
</tbody>)
}
}
//每行刷新控制
class Line extends Component{
constructor(props){
super(props)
this.currData={};
}
shouldComponentUpdate(nextProps,nextState){//改用手動控制每行渲染
if(!isEqual(nextProps.fields.get(nextProps.lineKey),this.currData)){
return true;
}
return false;
}
render(){
this.currData=this.props.get(this.props.lineKey)
console.log('//此處省略大量計算')
return (
<tr key={this.props.lineKey} >
<td>
<Field name={`${item}.name`} component={Field}/>
</td>
</tr>)
}
}
//數字輸入框
class Field extends Component{
shouldComponentUpdate(nextProps, nextState){//改用手動控制渲染
if(nextProps.input.name==this.props.input.name &&
nextProps.input.value==this.props.input.value &&
nextProps.className==this.props.className &&
nextProps.id==this.props.id &&
isEqual(nextProps.meta,this.props.meta)){
return false
}
return true
}
render(){
let {input}=this.props;
return <input {...input} />
}
}
複製代碼