认识高级组件
高阶函数的维基百科定义:至少满足以下条件之一
1、接受一个或多个函数作为输入;
2、输出一个函数;
JavaScript中比较常见的 filter、map、reduce 都是高阶函数
那么说明是高阶组件呢?
- 高阶组件的英文是 Higher-Order Components,简称为 HOC;
- 官方的定义:高阶组件是参数为组件,返回值为新组件的函数;
我们可以进行如下的解析:
- 首先,高阶组件 本身不是一个组件,而是一个函数;
- 其次,这个函数的参数是一个组件,返回值也是一个组件
高阶组件的定义
import React,{PureComponent } from 'react'
class App extends PureComponent [
render (){
return (
<div>
你好: {this.props.name}
</div>
)
}
function enhanceComponent(WrappedComponent) [
// 返回组件名NewComponent
// return class NewComponent extends PureComponent {
class NewComponent extends PureComponent {
render()[
return-<WrappedComponent {...this.props}/>
}
}
//组件的名称都可以通过displayName来修改
NewComponent.displayName= "kobe"; // 自定义组件名,一般开发调式才用到
return NewComponent;
}
const EnhanceComponent = enhanceComponent(App);
//export default App;
export default EnhanceComponent;
效果如下,
使用
<EnhanceComponent name="zhangsan">
- 高阶组件并不是React API的一部分,它是基于React的组合特性而形成的设计模式;高阶组件在一些React第三方库中非常常见:
- 比如redux中的 connect;
- 比如react-router中的 withRouter
高阶组件-props
案例一
import React,[ PureComponent ] from 'react';
class User1 extends PureComponent {
render(){
return <h3>Home: {`昵称: ${this.props.nickname} 等级: ${this.props.level} 区域:${this.props.region}`}</h3>
}
}
class User2 extends PureComponent {
render(){
return <h3>Home: {`昵称: ${this.props.nickname} 等级: ${this.props.level} 区域:${this.props.region}`}</h3>
}
}
// 定义一个高阶组件
function enhanceRegionProps(WrappedComponent) {
return props =>{
return <WrappedComponent {...props} refion="中国" />
}
}
const Person1 = enhanceRegionProps(User1 );
const Person2 = enhanceRegionProps(User2 );
class App extends PureComponent [
render(){
return(
<div>
App
// <User1 nickname="张三" level={90} />
// <User2 nickname="李四" level={30} />
<Person1 nickname="张三" level={90} />
<Person2 nickname="李四" level={30} />
</div>
}
}
}
export default App ;
案例二
import React,[ PureComponent ,createContext] from 'react';
// 创建Context
const UserContext = createContext({
nickname:"momo",
level:21,
region:'深圳'
})
class User1 extends PureComponent {
render(){
return <h3>Home: {`昵称: ${this.props.nickname} 等级: ${this.props.level} 区域:${this.props.region}`}</h3>
}
}
class User2 extends PureComponent {
render(){
return <h3>Home: {`昵称: ${this.props.nickname} 等级: ${this.props.level} 区域:${this.props.region}`}</h3>
}
}
// 定义一个高阶组件
function enhanceRegionProps(WrappedComponent) {
return props =>{
return <UserContext.Consumer>
{
user => {
// return <h3>Home: {`昵称: ${user.nickname} 等级: ${user.level} 区域:${user.region}`}</h3>;
return <WrappedComponent {...props} {...user} />
}
}
<UserContext.Consumer/>
}
}
const Person1 = enhanceRegionProps(User1 );
const Person2 = enhanceRegionProps(User2 );
class App extends PureComponent [
render(){
return(
<div>
App
<UserContext.Provider value={{nickname:"why" ,level:23,region:'上海'}} >
<Person1 />
<Person2 />
</ UserContext.Provider>
</div>
}
}
}
export default App ;
高阶组件存在的意义
-
我们会发现利用高阶组件可以针对某些React代码进行更加优雅的处理
其实早期的React有提供组件之间的一种复用方式是mixin,目前已经不再建议使用:- Mixin 可能会相互依赖,相互耦合,不利于代码维护
- 不同的Mixin中的方法可能会相互冲突
- Mixin非常多时,组件是可以感知到的,甚至还要为其做相关处理,这样会给代码造成滚雪球式的复杂性
-
当然,HOC也有自己的一些缺陷:
- HOC需要在原组件上进行包裹或者嵌套,如果大量使用HOC,将会产生非常多的嵌套,这让调试变得非常困难
- HOC可以劫持props,在不遵守约定的情况下也可能造成冲突;
-
Hooks的出现,是开创性的,它解决了很多React之前的存在的问题口比如this指向问题、比如hoc的嵌套复杂度问题等等
Portal 的使用
某些情况下,我们希望渲染的内容独立于父组件,甚至是独立于当前挂载到的DOM元素中(默认都是挂载到id为root素上的)
- Portal 提供了一种将子节点染到存在于父组件以外的 DOM 节点的优秀的方案:
- 第一个参数(child)是任何可染的 React 子元素,例如一个元素字符串或 fragment;
- 第二个参数(container)是一个 DOM 元素;就是要挂载到那个DOM上面
ReactDOM.createPortal(child,container);
通常来讲,当你从组件的 render 方法返回一个元素时,该元素将被挂载到DOM节点中离其最近的父节点