专栏名称: 唐左
前端高级开发工程师
目录
相关文章推荐
闹闹每日星运  ·  内心小秘密最多的星座 ·  2 天前  
闹闹每日星运  ·  十二星座如何化缺点为优点 ·  4 天前  
闹闹每日星运  ·  十二星座吃醋排行榜 ·  3 天前  
闹闹每日星运  ·  假期最不爱凑热闹的星座 ·  5 天前  
闹闹每日星运  ·  星历0129:金牛扩大交际圈 摩羯适合放松 ·  4 天前  
51好读  ›  专栏  ›  唐左

redux-form性能优化

唐左  · 掘金  ·  · 2018-01-02 06:02

正文

最近项目中使用redux-form遇上性能瓶颈,

需要100行以上联动表单变得极其卡

原因

  • 组件过多渲染导致! 更改一个输入框导致所有输入框都重新渲染。

解决思路

  • Field 使用 PureComponent 减少不必要的渲染[如果无效用shouldComponentUpdate ]

  • 推荐使用shouldComponentUpdate 精确控制到每行及每个输入框的渲染

  • 覆盖掉redux-from的onChange事件 改用onFocus和onBlur

下面代码我在FormMembers里遍历了fields,所以FormMembers重新渲染时会导致fields全部重新渲染。

优化后使用shouldComponentUpdate控制到每一行及每一个输入框的重新渲染,提高了非常多的性能!

优化前代码及结构

//表单
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} />
	}
}

优化后

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} />
	}
}

建议使用 reselect 优化性能

github.com/reactjs/res…

推荐文章
闹闹每日星运  ·  内心小秘密最多的星座
2 天前
闹闹每日星运  ·  十二星座如何化缺点为优点
4 天前
闹闹每日星运  ·  十二星座吃醋排行榜
3 天前
闹闹每日星运  ·  假期最不爱凑热闹的星座
5 天前
闹闹每日星运  ·  星历0129:金牛扩大交际圈 摩羯适合放松
4 天前
最搞笑笑话王  ·  爷爷奶奶带孙子,看完不许笑
7 年前