😊文章略長,作好內心準備哦,建議閱讀15分鐘。html
在下面不少案例中用到了裝飾器(@),這裏提早說明下,修飾器(Decorator)是一個函數,用來修改類的行爲。react
更多用法可參考簡書一篇文章:www.jianshu.com/p/275bf41f4…es6
const EnhancedComponent = higherOrderComponent(WrappedComponent)bash
function hoc(WrappedComponent) {
return class HOC extends React.Component {
componentDidMount() {
console.log("hoc");
}
render() {
return <WrappedComponent />
}
}
}
// 使用高階組件
class ComponentClass extends React.Component {
render() {
return <div></div>
}
}
export default hoc(ComponentClass);
// 做爲裝飾器使用
@hoc
export default class ComponentClass extends React.Component {
//...
}
複製代碼
// 添加新的props
function ppHOC(WrappedComponent) {
return class PP extends React.Component {
render() {
const newProps = {
user: currentLoggedInUser
}
return <WrappedComponent {...this.props} {...newProps}/>
}
}
}
複製代碼
// WrappedComponent初始渲染時候會調用ref回調,傳入組件實例,在proc方法中,就能夠調用組件方法
function refsHOC(WrappedComponent) {
return class RefsHOC extends React.Component {
proc(wrappedComponentInstance) {
wrappedComponentInstance.method()
}
render() {
// Object.asign();將全部可枚舉屬性的值從一個或多個源對象複製到目標對象
const props = Object.assign({}, this.props, {ref: this.proc.bind(this)})
return <WrappedComponent {...props}/>
}
}
}
複製代碼
// 提取了 input 的 value 和 onChange 方法
function ppHOC(WrappedComponent) {
return class PP extends React.Component {
state = {
name: ''
}
onNameChange(event) {
this.setState({
name: event.target.value
})
}
render() {
const newProps = {
name: {
value: this.state.name,
onChange: this.onNameChange.bind(this)
}
}
return <WrappedComponent {...this.props} {...newProps}/>
}
}
}
// 使用方式以下
@ppHOC
class Example extends React.Component {
render() {
// 使用ppHOC裝飾器以後,組件的props被添加了name屬性,input會成爲受控組件
return <input name="name" {...this.props.name}/>
}
}
複製代碼
function ppHOC(WrappedComponent) {
return class PP extends React.Component {
render() {
return (
<div style={{display: 'block'}}>
<WrappedComponent {...this.props}/>
</div>
)
}
}
}
複製代碼
// 過濾掉原組件中的ul元素
function hoc(ComponentClass) {
return class HOC extends ComponentClass {
render() {
const elementTree = super.render();
elementTree.props.children = elementTree.props.children.filter((z) => z.type !== "ul")
return React.cloneElement(elementTree);
}
}
}
@hoc
export default class ComponentClass extends React.Component {
render() {
return (
<div>
<p style={{color: 'brown'}}>啦啦啦</p>
<ul>
<li>1</li>
<li>2</li>
</ul>
</div>
)
}
}
複製代碼
export function IIHOC(WrappedComponent) {
return class II extends WrappedComponent {
render() {
return (
<div>
<p>Props</p> <pre>{JSON.stringify(this.props, null, 2)}</pre>
<p>State</p><pre>{JSON.stringify(this.state, null, 2)}</pre>
{
super.render()
}
</div>
)
}
}
}
複製代碼
// 假設this.props.loggedIn爲真,HOC會徹底渲染WrappedComponent 的渲染結果
function iiHOC(WrappedComponent) {
return class ii extends WrappedComponent {
render() {
if (this.props.loggedIn) {
return super.render()
} else {
return null
}
}
}
}
複製代碼
// 用HOC包裹的組件會丟失原先的名字,影響開發和調試,能夠在WrappedComponent的名字加前綴來做爲HOC的名字
const componentName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
static displayName = `withModal(${componentName})`;
複製代碼
//經過多重高階組件肯定key並設定組件
const withStorage = (key) => WrappedComponent => {
return class extends Component {
componentWillMount() {
let data = localStorage.getItem(key);
this.setState({data});
}
render() {
return <WrappedComponent data={this.state.data} {...this.props} />
}
}
}
@withStorage('data')
class MyComponent2 extends Component {
render() {
return <div>{this.props.data}</div>
}
}
@withStorage('name')
class MyComponent3 extends Component {
render() {
return <div>{this.props.data}</div>
}
}
複製代碼
const modalHoc = (options) => WrappedComponent => {
const componentName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
return class ModalComponent extends Component {
static displayName = `withModal(${componentName})`;
render() {
const {visible, onCancel} = this.props;
let title;
if (typeof options === 'string') title = options;
if (typeof options === 'function') title = options;
if (typeof options === 'object') title = options.title;
if (typeof title === 'function') title = title(this.props);
return (
<Modal
destroyOnClose
width="60%"
bodyStyle={{padding: 0}}
footer={null}
{...options}
title={title}
onCancel={onCancel}
visible={visible}
>
<WrappedComponent {...this.props}/>
</Modal>
);
}
}
};
@modalHoc('能夠傳入不一樣類型標題')
複製代碼
😊 參考連接:react.html.cn/docs/higher…app
😊 剛剛加入掘金社區,歡迎提出寶貴建議,一塊兒進步學習!函數