# 大纲

高阶大纲 (opens new window)密码:4851

# 高阶组件分类

# 属性代理

import React from 'react';

class Home extends React.Component {
	render() {
		return 'home';
	}
}

function HOC(Component) {
	return class Index extends React.Component {
		render() {
			return <Component {...this.props}/>;
		}
	};
}

export default HOC(Home);

# 反向继承

import React from 'react';

class Home extends React.Component {
	render() {
		return 'home';
	}
}

function HOC(Component) {
  // 继承
	return class Index extends Component {
		render() {
			return <Component />;
		}
	};
}

export default HOC(Home);

# 怎么编写高阶组件

# 强化props

import React from 'react';

class Home extends React.Component {
	componentDidMount = () => {
		this.props.sayHi && this.props.sayHi();
	};

	render() {
		return 'home';
	}
}

function HOC(Component) {
	return class Index extends React.Component {
		sayHi = () => alert('hi');
		render() {
      // 增强 props
			return <Component sayHi={this.sayHi} {...this.props} />;
		}
	};
}

export default HOC(Home);

# 控制渲染

# 渲染劫持

import React from 'react';

// 注意:不能是函数组件
class Home extends React.Component {
	render() {
		return <div>home</div>;
	}
}

const HOC = (Component) => {
	return class Index extends Component {
		render() {
			if (this.props.visible) {
        // 反向继承,可以通过 super.render() 得到传入组件渲染的结果
				return super.render();
			} else {
				return <div>暂无数据</div>;
			}
		}
	};
};

class HocHome extends React.Component {
	render() {
		const Temp = HOC(Home);
		return <Temp visible={true} />;
	}
}
export default HocHome;

# 修改渲染树

import React from 'react';
class Home extends React.Component {
	render() {
		return <span>hello</span>;
	}
}

function HOC(Component) {
	return class Index extends Component {
		render() {
			const element = super.render();
			const tempEl = <span>hello world</span>;
			const newEl = React.Children.map(element.props.children, (child, index) => {
				if (index === 0) return tempEl;
				return child;
			});
			return React.cloneElement(element, element.props, newEl);
		}
	};
}

export default HOC(Home);

页面展示 hello

# 组件赋能

# ref获取实例

import React from 'react';

function HOC(Component) {
	return class WrapComponent extends React.Component {
		constructor(props) {
			super(props);
      // 获取组件实例
			this.node = null;
		}
		componentDidMount = () => {
			// 获取组件状态或者执行组件方法
			this.node.handleClick();
		};

		render() {
			return <Component ref={(node) => (this.node = node)} />;
		}
	};
}
class Home extends React.Component {
	handleClick = () => console.log('自动执行');
	render() {
		return 'home';
	}
}

const HocHome = HOC(Home);
export default () => {
	return <HocHome />;
};

# 事件监控

import React, { useEffect, useRef } from 'react';

function HOC(Component) {
	return function() {
		const node = useRef(null);
		useEffect(() => {
			const handleClick = () => console.log('点击了');
			node.current.addEventListener('click', handleClick);
			return () => node.current.removeEventListener('click', handleClick);
		}, []);
		return (
			<div ref={node}>
				<Component ref={node} />
			</div>
		);
	};
}
// 这里装饰的不能是个函数
@HOC
class Home extends React.Component {
	render() {
		return <button>Home页面的button</button>;
	}
}

export default () => {
	return <Home />;
};

效果图:

# 权限拦截

import React, { useState } from 'react';
const PermissionContext = React.createContext([]);

function PermissionHoc(authorization) {
	return (Component) => {
		return () => {
			const matchPermission = (value, list) => list.indexOf(value) >= 0;
			return (
				<PermissionContext.Consumer>
					{(permissionList) =>
						matchPermission(authorization, permissionList) ? <Component /> : <NoPermission />}
				</PermissionContext.Consumer>
			);
		};
	};
}

function NoPermission() {
	return <div>您没有操作权限</div>;
}
function Add() {
	return 'add';
}
function Del() {
	return 'del';
}
const HocDel = PermissionHoc('del')(Del);
const HocAdd = PermissionHoc('add')(Add);
export default () => {
	const [ permission ] = useState([ 'add' ]);
	return (
		<PermissionContext.Provider value={permission}>
			<HocAdd />
			<HocDel />
		</PermissionContext.Provider>
	);
};

展示效果