React
性能优化
- 渲染数组中传递给子组件的方法bind问题
- 少写部分代码
问题
在渲染列表时, 传递给子组件的方发需要绑定参数, 每次render 都会产生新的方法传递给子组件
list.map(record => {
return <SomeComponent onMethod={this.handleMethod.bind(record)} />
// return <SomeComponent onMethod={() => {this.handleMethod(record)}} />
})
问题解决
包装一个新组件来处理每次都产生新的方法的问题
class WrapSomeComponent extends React.Component {
constructor() {
this.handleMethod = this.handleMethod.bind(this);
}
handleMethod() {
const { record, onMethod } = this.props;
onMethod(record);
}
render() {
const { onMethod, ...rest } = this.props;
return <SomeComponent onMethod={this.handleMethod} {...rest} />;
}
}
class Page extends React.Component {
render() {
const { list } = this.props;
return (
list.map(record => {
return <WrapSomeComponent onMethod={this.handleMethod} record={record} />
})
);
}
}
通用方法
使用高阶组件来注入 bind 的方法
import {isEmpty, isString, omit} from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
export function proxyComponentMethod(options) {
const {
config = [
{
method: 'onClick',
args: ['record'],
}
],
omitProps = [],
} = options || {};
const propTypes = {};
config.forEach(({method}) => {
propTypes[method] = PropTypes.func.isRequired;
});
return function ProxyComponentMethod(ProxyComponent) {
const displayName = isString(ProxyComponent)
? ProxyComponent : (ProxyComponent.displayName || ProxyComponent.name || 'UnKnow');
return class ProxyMethodComponent extends React.Component {
static displayName = displayName;
static propTypes = propTypes;
constructor(props) {
super(props);
const proxyMethods = {};
config.forEach(({method, args = []}) => {
proxyMethods[method] = (...oriArgs) => {
const {[method]: proxyMethod} = this.props;
proxyMethod(...args.map((arg) => this.props[arg]), ...oriArgs);
}
});
this.proxyMethods = proxyMethods;
}
render() {
if (isEmpty(omitProps)) {
return (React.createElement(ProxyComponent, {...this.props, ...this.proxyMethods}));
} else {
return (React.createElement(ProxyComponent, {...omit(this.props, omitProps), ...this.proxyMethods}));
}
}
}
}
}
-
使用通用方法注解的组件
image.png -
使用代理之后的组件
image.png