当不同组件有相似功能时,可以进行复用,其实本质是复用组件的state和操作state的方法,即组件逻辑,复用方式有如下两种:
1.render-porps模式
2.高阶组件(HOC)
这两种方式不是新的API,而是利用react自身特点的编码技巧,演化而成的固定模式。
render-porps模式
思路:将复用的state和操作state的方法封装到一个组件中;
方法:
1.在使用组件的时候,添加一个函数prop(render),通过函数可以拿到组件内部需要操作的数据。
2.将想要渲染的ui结构放在render函数中返回回来。
//定义复用组件
class ComComponent extends React.component {
//省略state,和state方法
render(){
// 先拿到父组件传给复用组件的自定义函数render,
// 然后调用这个函数,将内部的state通过自定以组件render暴露到组件外部
return this.props.render(this.state)
}
}
//使用复用组件
<ComComponent render={ data=> {
return (
<p> ui结构,拿到的数据是:{data} </p>
)
}
/>
注:从优化的角度来看,应该在组件卸载时接触里面操作state的方法,例如
componentWillUnmount() {
window.removeEventListener(...)
}
高阶组件(HOC)
高阶组件是一个函数,接受要被包装的组件,返回增强后的组件
使用步骤:
1.创建一个函数,以with开头
2.指定函数参数,参数应以大写字母开头,因为要作为要渲染的组件
3.在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
4.在该组件中,渲染参数组件,同时将状态通过prop传递给参数组件
5.调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
//创建高阶组件
function withComponent(WrappedComponent) {
class Component extends React.component{
// 省略了state和操作state的逻辑代码
render(){
return <WrappedComponent {...this.state} />
}
}
return Component
}
//使用高阶组件
const HOC = withComponent(WrappedComponent)
//渲染高阶组件
<HOC />
使用高阶组件存在的问题:得到的两个组件名称相同
解决方式:为高阶组件设置displayName便于调试时区分不同组件
// 上述组件如果复用, 则在结构中名称都是componen
Component.displayName= `WithComponent${gerDisplayName(WrappedCompnent)}`
function gerDisplayName(WrappedCompnent) {
return WrappedCompnent.displayName || WrappedCompnent.name || 'component'
}
在高阶组件中传递props时的问题:
//获取经过包装的高级组件useComponent
const useComponent = withComponent(wrappedComponent)
// 在某个父组件中进行使用
class APP extends React.Component{
//省略了state和操作state的方法
render() {
return(
<useComponent a='1' />
)
}
}
如果像这样在被包装后的高阶组件中传入一个props a='1'时,实际上时传递给了高阶组件内部的class component,而高阶组件并没有往下进行传递,造成了丢失。
解决方法:渲染时,将state和this.props一起传递
class APP extends React.Component{
//省略了state和操作state的方法
render() {
return(
<useComponent {...this.state} {...this.props} />
)
}
}