react native优化class组件的几个方法。优化渲染时间,减少渲染次数

1. 目的:

  • 优化渲染速度
  • 减少渲染次数

2. 优化流程:

2.1 梳理组件结构

优化后的结构图
–略

2.2 需要优化的内容

针对渲染时间和渲染次数进行优化

减少渲染时间:

  1. 避免内联函数定义 → 每次重新渲染都重新创建函数实例,VDom属性改变,dom节点重新渲染。
//bad: onClick方法中,使用了内联匿名函数
<Comp onClick={(e)=>{this.setState({isClick:ture})}} key={item.id}/>

//good: 声明函数
const handleClick = (e) => this.setState({isClick:ture})

<Comp onClick={handleClick} key={item.id}/>
  1. 避免内联组件定义 → 每次都重复创建匿名组件实例,引起Comp VDom变更,dom节点重新渲染
//bad: onClick方法中,使用了内联匿名组件
<Comp prop={<View props={this.state.name}> ... </View>} key={item.id}/>

//good: 声明组件
const propComp = (props: {name}) => (<View props={name}> ... </View>)

<Comp prop={propComp} key={item.id}/>
  1. 避免内敛style定义 → 更新vdom,重新渲染
//bad : 
<Comp style={{flex: 1}} />

//good: 

flex: {
	flex: 1
}

<Comp style={flex} />
  1. 减少render函数内声明 → 每次重新渲染都会执行render函数,在render函数中定义子组件或方法,会增加每次重新渲染耗时。若是较大的组件或等待方法,耗时更明显

    //bad: 每次重新渲染都会重新创建navBarLeftRender与handlePageBack
    class ScanList extends React.Component<ScanListProps, ScanListState> {
    	...
    	...
    	render() {
    		const navBarLeftRender = (
    			<TouchableOpacity
    				onPress={hadnlePageBack}
    				... 
    			/>
    		)
    		const handlePageBack = async() => {
    			await this.props?.onBack?.();
    		}
    	
    		return (
    			<View>
    				<NavBar leftProps={navBarLeftRender} />
    				...
    			</View>
    		)
    	}
    }
    
    //good: 将render中声明的函数与组件都拿到render外
    class ScanList extends React.Component<ScanListProps, ScanListState> {
    	...
    	const navBarLeftRender = (
    		<TouchableOpacity
    			onPress={hadnlePageBack}
    			... 
    		/>
    	)
    	const handlePageBack = async() => {
    		await this.props?.onBack?.();		
    	}
    	...
    	render() {
    	...	
    		return (
    			<View>
    				<NavBar leftProps={navBarLeftRender} />
    				...
    			</View>
    		)
    	}
    }
    
  2. 记忆子组件 → 在引用的props不变更的情况下,不因父组件重新渲染而引起子重新渲染。

    //bad: 无论leftProps是否更新,NavBar总是随着ScanList组件重新渲染。
    	render() {
    	...	
    		return (
    			<View>
    				<NavBar leftProps={navBarLeftRender} />
    				...
    			</View>
    		)
    	}
    
    //good: 只在leftProps更新时渲染
    const MemoNavBar = memo(NavBar)
    	render() {
    	...	
    		return (
    			<View>
    				<MemoNavBar leftProps={navBarLeftRender} />
    				...
    			</View>
    		)
    	}
    
    
  3. 长列表优化 → 目前组件用到的flatList没有使用官方推荐的优化属性, 如: maxToRenderPerBatch, initialNumToRender

减少渲染次数:

引起重新渲染主要场景:

  1. 组件状态变更[略]

  2. 父组件渲染导致子组件重新渲染

    1. 梳理出每个子组件使用到的state,状态下放。

      //bad: 若点击button,会触发整个Component的更新,导致veryslowComponent也重新渲染
      const Component = () => {
      	const [open, setOpen] = useState(false);
      	return (
      		<Something>
      			<Button onClick={()=> setOpen(true)}
      			{isOpen && <ModalDialog />}
      			<VerySlowComponent />
      		</Something>
      	)
      }
      
      //good: 将只作用在Dialog的open state集中到ButtonWithDialog中
      //open更新只引起ButtonWithDialog的重新渲染, VerySlowComponent不受影响
      
      const ButtonWithDialog = () => {
      	const [open, setOpen] = useState(false);
      	return (
      		<>
      			<Button onCLick={() => setOpen(true)} />
      			{isOpen && <ModalDialog />}
      		</>
      	)
      }
      const Component = () => {
      	return (
      		<Something>
      			<ButtonWithDialog />
      			<VerySlowComponent />
      		</Something>
      	)
      }
      
    2. 记忆组件

      通过PureComponent,或者memo,或者shouldComponentUpdate 控制class组件是否有必要重新渲染。

    3. 基于b,使用组件的页面,若每次都传入重新定义的pure function可以使用usecallback , usememo,减少引起scanList重新渲染次数

  3. context变更导致引用的组件重新渲染[略]

  4. hooks内状态变更触发重新渲染[略]

3. 具体优化内容

-略

4 前后对比

通过flipper performace记录优化后的各项值,前后对比

最终优化性能对比:

直观的火焰图: 可以看到渲染次数和渲染时间都比初始大大减少

在这里插入图片描述
页面操作耗时对比:
在这里插入图片描述

5. 遗留:

emulator随网络波动,cpu运行情况 影响大,同一修改节点,刷新前后渲染时长有较大差异,用真机更可靠,但目前真机无法使用filpper的profilling。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值