迎接关注我的民众号睿Talk
,猎取我最新的文章:
一、媒介
在一样平常开辟和 Code Review 的时刻,常常会发明一些共性的题目,也有许多值得首倡的做法。本文针对 React 手艺栈,总结了一些最好实践,对编写高质量的代码有一定的参考作用。
二、最好实践 & 申明
多用 Function Component
假如组件是纯展现型的,不须要保护 state 和生命周期,则优先运用 Function Component。它有以下优点:
- 代码更简约,一看就晓得是纯展现型的,没有庞杂的营业逻辑
- 更好的复用性。只需传入雷同构造的 props,就能够展现雷同的界面,不须要斟酌副作用。
- 更小的打包体积,更高的实行效力
一个典范的 Function Component 是下面这个模样:
function MenuItem({menuId, menuText, onClick, activeId}) {
return (
<div
menuId={menuId}
className={`${style} ${activeId === menuId ? active : ''}`}
onClick={onItemClick}
>
{menuText}
</div>
);
};
多用 PureComponent
假如组件须要保护 state 或运用生命周期要领,则优先运用 PureComponent,而不是 Component。Component 的默许行动是不管 state 和 props 是不是有变化,都触发 render。而 PureComponent 会先对 state 和 props 举行浅比较,差别的时刻才会 render。请看下面的例子:
class Child extends React.Component {
render() {
console.log('render Child');
return (
<div>
{this.props.obj.num}
</div>
);
}
}
class App extends React.Component {
state = {
obj: { num: 1 }
};
onClick = () => {
const {obj} = this.state;
this.setState({obj});
}
render() {
console.log('render Parent');
return (
<div className="App" >
<button onClick={this.onClick}>
点我
</button>
<Child obj={this.state.obj}/>
</div>
);
}
}
点击按钮后,Parent 和 Child 的 render 都邑触发。假如将 Child 改成 PureComponent,则 Child 的 render 不会触发,因为 props 照样同一个对象。假如将 Parent 也改成 PureComponent,则 Parent 的 render 也不会触发了,因为 state 照样同一个对象。
遵照单一职责准绳,运用 HOC / 装潢器 / Render Props 增添职责
比方一个公用的组件,数据泉源多是父组件传过来,又或许是本身主动经由过程收集要求猎取数据。这时刻能够先定义一个纯展现型的 Function Component,然后再定义一个高阶组件去猎取数据:
function Comp() {
...
}
class HOC extends PureComponent {
async componentDidMount() {
const data = await fetchData();
this.setState({data});
}
render() {
return (<Comp data={this.state.data}/>);
}
}
组合优于继续
笔者在实在项目中就试过以继续的情势写组件,本身写得很爽,代码的复用性也很好,但最大的题目是他人看不懂。我将复用的营业逻辑和 UI 模版都在父类定义好,子类只须要传入一些参数,然后再掩盖父类的几个要领就好(render的时刻会用到)。简化的代码以下:
class Parent extends PureComponent {
componentDidMount() {
this.fetchData(this.url);
}
fetchData(url) {
...
}
render() {
const data = this.calcData();
return (
<div>{data}</data>
);
}
}
class Child extends Parent {
constructor(props) {
super(props);
this.url = 'http://api';
}
calcData() {
...
}
}
如许的写法从言语的特征和功用完成来讲,没有任何题目,最大的题目是不符合 React 的组件编写习气。父类或许子类一定有一方是不须要完成 render 要领的,而平常我们看代码都邑优先找 render 要领,找不到就慌了。别的就是搞不清楚哪些要领是父类完成的,哪些要领是子类完成的,假如让其他人来保护这份代码,会比较费劲。
继续会让代码难以溯源,定位题目也比较贫苦。一切经由过程继续完成的组件都能够改写为组合的情势。上面的代码就能够够如许改写:
class Parent extends PureComponent {
componentDidMount() {
this.fetchData(this.props.url);
}
fetchData(url) {
...
}
render() {
const data = this.props.calcData(this.state);
return (
<div>{data}</data>
);
}
}
class Child extends PureComponent {
calcData(state) {
...
}
render() {
<Parent url="http://api" calcData={this.calcData}/>
}
}
如许的代码是不是是看起来惬意多了?
假如 props 的数据不会转变,就不须要在 state 或许组件实例属性里拷贝一份
常常会看见如许的代码:
componentWillReceiveProps(nextProps) {
this.setState({num: nextProps.num});
}
render() {
return(
<div>{this.state.num}</div>
);
}
num 在组件中不会做任何的转变,这类状况下直接运用 this.props.num 就能够够了。
防止在 render 内里动态建立对象 / 要领,否则会致使子组件每次都 render
render() {
const obj = {num: 1}
return(
<Child obj={obj} onClick={()=>{...}} />
);
}
在上面代码中,纵然 Child 是 PureComponent,因为 obj 和 onClick 每次 render 都是新的对象,Child 也会随着 render。
防止在 JSX 中写庞杂的三元表达式,应经由过程封装函数或组件完成
render() {
const a = 8;
return (
<div>
{
a > 0 ? a < 9 ? ... : ... : ...
}
</div>
);
}
像上面这类嵌套的三元表达式可读性异常差,能够写成下面的情势:
f() {
...
}
render() {
const a = 8;
return (
<div>
{
this.f()
}
</div>
);
}
多运用解构,如 Function Component 的 props
const MenuItem = ({
menuId, menuText, onClick, activeId,
}) => {
return (
...
);
};
定义组件时,定义 PropTypes 和 defaultProps
例子以下:
class CategorySelector extends PureComponent {
...
}
CategorySelector.propTypes = {
type: PropTypes.string,
catList: PropTypes.array.isRequired,
default: PropTypes.bool,
};
CategorySelector.defaultProps = {
default: false,
type: undefined,
};
防止运用无谓的标签和款式
下面这类状况平常外层的div
是过剩的,能够将款式直接定义在组件内,或许将定制的款式作为参数传入。破例:当ServiceItem
须要在多个处所运用,而且要叠加许多不一样的款式,原写法会轻易些。
// bad
<div key={item.uuid} className={scss.serviceItemContainer}>
<ServiceItem item={item} />
</div>
// good
<ServiceItem key={item.uuid} item={item} className={customStyle} />
三、总结
本文列举了笔者在项目实战和 Code Review 过程当中总结的 10 条最好实践,当中的一些写法和准绳只代表个人态度。明白并遵照这些最好实践,写出来的代码质量会有一定的保证。假如你有差别的看法,或许有补充的最好实践,迎接留言交换。