高阶函数(HOC)
为了提高组件复用率,可测试性,就要保证组件功能单⼀性;
但是若要满⾜复杂需求就要扩展功能单⼀的组件,在React里就有了HOC(Higher-Order Components)的概念。
定义: ⾼阶组件是参数为组件,返回值为新组件的函数
最为出名的就是 redux 中的 connect函数
// hoc.js
import React from 'react'
/**
高阶组件-HOC
为了了提高组件复用率,可测试性,就要保证组件功能单一性;但是
若要满足复杂需求就要扩展功能单一的组件,在React里就有了
HOC(Higher-Order Components)的概念。
定义: ⾼高组件是参数为组件,返回值为新组件的函数
最为出名的就是 redux 中的 connect函数
*/
// foo函数 接受一个函数, 返回新的组件
// Com 这里是指 function 或者 class组件
const foo = (Com) => (props) => {
return (
<div className="red-bd">
<Com {...props}></Com>
</div>
)
}
const foo2 = (Com) => (props) => {
return (
<div className="blue-bd">
<Com {...props}></Com>
</div>
)
}
// 其他写法
// higherOrderComponent 接受了一个组件 wrappedComponent
const higherOrderComponent = (wrappedComponent)=>{
// 做些逻辑判断可以返回其他函数
class HOC extends React.Component {
render(){
return <WrappedComponent />
}
}
// 返回一个新的组件
return HOC
}
function Child(props) {
return <div>我是Child {props.name}</div>
}
export default foo2(foo(Child))
// app.css
.red-bd {
border: 1px solid #f00;
padding: 5px;
}
.blue-bd {
border: 1px solid #00f;
padding: 5px;
}
// app.js
import React from 'react'
import Hoc from './views/Hoc'
import './App.css'
function App() {
return (
<div className="App">
<Hoc name="test" />
</div>
)
}
export default App
- 效果如下图
![](https://img.haomeiwen.com/i7924287/a795b8be6db9c138.png)
装饰器写法
高阶组件本身是对装饰器器模式的应⽤用,自然可以利用ES7中出现的装饰器语法来更优雅的书写代码。
yarn add customize-cra react-app-rewired --dev
yarn add @babel/plugin-proposal-decorators --dev
更新 config-overrides.js
// config-overrides.js
//配置完成后记得重启下
const { override, addDecoratorsLegacy } = require('customize-cra')
module.exports = override(
addDecoratorsLegacy() //配置装饰器器
)
// 同时还要修改 package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
},
装饰器写法修改 Child组件
// 装饰器写法
// 装饰器只能用在class组件上
// 执行顺序从下往上
@foo2
@foo
class Child1 extends Component {
render() {
return <div>我是装饰器写法 {this.props.name}</div>
}
}
export default Child1
使用HOC的注意事项
不要在render方法中使用HOC
React 的 diff 算法(称为协调)使⽤组件标识来确定它是应该更新现有子树还是将其丢弃并挂载新子树。 如果从 render 返回的组件与前一个渲染中的组件相同( ===),则 React 通过将⼦树与新子树进行区分来递归更新子树。 如果它们不相等,则完全卸载前一个子树 。
render() {
// 每次调⽤用 render 函数都会创建⼀一个新的
EnhancedComponent
// EnhancedComponent1 !== EnhancedComponent2
const EnhancedComponent = enhance(MyComponent);
// 这将导致⼦子树每次渲染都会进⾏行行卸载,和重新挂载的操作!
return <EnhancedComponent />;
}
不仅仅是性能问题 - 重新挂载组件会导致该组件及其所有子组件的状态丢失
网友评论