React逻辑复用的方案?
HOC
HOC(高阶组件)类似于高阶函数,在使用高阶组件时,传入一个组件,会返回一个组件
withRouter:这个高阶组件的作用是复用传递给视图组件路由信息这个逻辑
使用方法
function Acmp(props){
const { history,location,match } = props
return <div>视图</div>
}
const Bcmp = withRouter(Acmo)
这里我们有一个普通组件 Acmp ,本身并不具有路由相关信息. 如果我们在 Acmp 中想要使用路由相关的信息,可以使用 withRouter 这样 Acmp 就拥有了路由信息. 在使用的时候只要调用withRouter,然后把Acmp 传递进去,withRouter 会返回一个 Bcmp 在调用 Bcmp 时,会调用 Acmp,并将路由信息传递给 Acmp.
原理
const withRouter = (Cmp) => {
return () => {
return <Route component = {Cmp} />
}
}
hooks
hooks 的出现,主要目的就是解决逻辑复用问题,相比于高阶组件,hooks 的使用更灵活,更自由. 在使用 withRouter 时,会一次性将路由所有相关数据导入组件, 而 hooks ,我们按照需求只导入 location 或 history.如果另外一个组件中,要复用多个逻辑时,高阶组件明显使用起来就比较不便.
比如在 Acmp 组件中,我们既需要使用 Redux 相关数据,又需要路由信息时,就回出现每复用一个逻辑就需要包一层,极其不方便
function Acmp(props){
const { history,location,match } = props
return <div>视图</div>
}
const Bcmp = withRouter(Acmo)
const Ccmp = connect(state => state)(Bcmp)
render props
render props 是react复用逻辑的小技巧,react组件具有一个render 属性,该属性接收的是一个函数,该组件中要渲染的视图是 render 属性的返回值
比如我们使用最多也最常见的Route 组件的 render 属性:
<route path='/home' render ={() => {
return <HomeView />
}}>
Route 组件中的这个 render 属性就是一个关于 render props 的实际应用,将组件内要渲染的视图放在 render属性的返回值中,而组件本身是一个路由逻辑的共用。 这样就做到了功能复用而视图自定义.
原理:
function Route(props){
const {path,render} = props
if(matchPath(path)){
return <RouteContext.Consumer>
{(context) => {
return render(context)
}}
<RouteContext.Consumer>
}
return null
}
三者之间的差异
1、高阶组件可以做的事情,hooks 都可以去做,而且 hooks 的使用比高级组件更灵活也更方便,但是hooks 只能用在函数组件下
2、高阶组件或hook,通常用在单一的逻辑复用
比如实时获取当前滚动条位置,或定义state,副作用处理等,都是单一的逻辑
3、 render props 通常是一个完整的功能复用,只是该功能中视图或部分视图需要由使用者定义
比如,弹窗功能,路由功能 等