前端
在软件工程中,如何减少重复劳动一直是程序员所关心的问题.在前端工程领域,围绕这一问题所提出的解决方案大大推动了前端的发展.React/Vue/Angular三大框架正是因为使用了组件化这一目前最佳的解决方案而知名.
React
而在React开发的过程中,组件往往只能解决View层的重复逻辑,对于Model层的逻辑来说组件的可复用性并不够强大.所幸这一问题,在开发者们的努力下,目前已经出现相对成熟的方案.其中可用性最好的有三种:HOC/render props/react hooks.
HOC
HOC,又名高阶组件.其特征是入参中至少有一个为组件,出参必然为一个组件.
以按钮权限为例:
/* 根据moduleId判断是否显示组件
- @params {Component} component 要显示的组件
- @params {Array} authArr 权限数组
- @params {string} moduleId 模块id
*/
function shouldShowBtn(component, authArr, moduleId){
const shouldShow = src.some(item => item.moduleId === moduleId);
if(shouldShow){
return component;
}else{
return null;
}
}
// 在页面中使用
const Btn = shouldShowBtn(, [], ‘00001’);
render(){
return ;
}
这样变实现了权限判断逻辑的复用.
render props
HOC能够实现逻辑复用,但是如果涉及到组件生命周期时,往往需要在返回值中创建一个新的匿名组件,在该匿名组件的生命周期中编写可复用逻辑.
对于这种不够优雅的写法,我们可以使用render props来改善.
class Subscribe extends React.Component{
constructor(props){
super(props);
this.state={
logged: false
};
}
componentDidMount(){
this.setState({
logged: true
})
}
componentWillUnmount(){
this.setState({
logged: false
})
}
render(){
const { renderCom } = this.props;
const { logged } = this.state;
return {renderCom(logged)}
}
}
hooks
目前来看,HOC与render props两种解决方案各有千秋,前者更适用于做静态数据的逻辑处理,而后者适用于涉及到组件状态变化的逻辑处理.可以说是涵盖了我们日常开发中的大多数应用场景.
而在2019年2月,React给出了一个官方API: hooks.它脱离了原有的类组件思维,回归了组件即函数的思想.
首先,它解决的问题与上文所述的两种方案一致,都是为了实现逻辑复用.其次,对于HOC无法使用ref的问题,还提供了useRef功能.另外,它的写法能够避免render props带来的容器组件嵌套过多的问题.
以展示用户登录状态为例
import React, { useState, useEffect } from ‘react’;
// 自定义hooks
function useLogged() {
const [logged, setLogged] = useState(false);
useEffect(() => {
// 登录
setLogged(true);
return () => {
setLogged(false);
}
});
return logged
}
// 登录状态
function LogStatus() {
const logged = useLogged();
return logged ? ‘Online’ : ‘Offline’;
}
// 好友列表
function FriendList() {
const logged = useLogged();
return {logged ? (
- 张三
- 张三
- 张三
) : null};
}
相比较于HOC和render props,使用自定义hooks后,代码逻辑简洁优雅,且没有过多的嵌套.
个人推荐在以后的开发中接触/习惯react hooks的写法.