内容简介:高阶组件(HOC)是译注:对,我又一次借鉴了官网 :joy:他们接收一个组件并返回一个新的组件!
React Components 中重复逻辑! :sunglasses:
原文: React Higher Order Components in 3 minutes
作者:Jhey Tompkins
译者:博轩
什么是高阶组件?
高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。 HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。
译注:对,我又一次借鉴了官网 :joy:
它做了什么?
他们接收一个组件并返回一个新的组件!
什么时候去使用?
当你的组件之间出现重复的模式 / 逻辑的时候。
栗子:
- 挂载,订阅数据
- 为
UI增加交互(也可以使用容器组件,或者 Render Props ) - 排序,过滤输入的数据
译注:第三个说法,我个人可能更加倾向于在传入组件之前做处理,而不是使用高阶组件
一个愚蠢的例子
我们有一个 Mouse 组件。
const Mouse = () => (
<span className="mouse" role="img">:mouse:</span>
)
接下来,让我们使用 GreenSock’s Draggable 模块,来让组件变的可以拖拽。
class Mouse extends Component {
componentDidMount = () => new Draggable(this.ELEMENT)
render = () => (
<span className="mouse" ref={e => (this.ELEMENT = e)} role="img">:mouse:</span>
)
}
我们加一只 猫 :cat:
const Cat = () => (
<span className="cat" role="img">:cat:</span>
)
这个组件同样需要变得可拖拽:hand:,接下来,让我们使用高阶组件(HOC)来试一下:
const withDrag = Wrapped => {
class WithDrag extends Component {
componentDidMount = () => new Draggable(this.ELEMENT)
render = () => {
return (
<span className="draggable_wrapper" ref={e => (this.ELEMENT = e)}>
<Wrapped {...this.props} />
</span>
)
}
}
WithDrag.displayName = `WithDrag(${Wrapped.displayName || Wrapped.name})`
return WithDrag;
}
我们的高阶组件(HOC)可以通过 props 接受一组件,并返回一个新的组件。
许多高阶组件会在传递组件的过程中,注入新的 props 。这通常是决定我们是否应该使用高阶组件的因素之一。如果,我们不注入 props ,我们可以使用一个容器组件,或者 Render Props 。
对于我们的高阶组件(HOC),我们也可以使用 Render Props 来达到相同的效果。你可能会觉得使用 HOC 来实现并不合适。但是,这个 “愚蠢的例子” 会让你更加熟悉 HOC 。 这比注入数据的示例更加有趣!:wink:
让我们将这个 HOC 应用到 Cat 和 Mouse 组件上吧 :+1:
const Mouse = () => (
<span className="mouse" role="img">:mouse:</span>
)
const Cat = () => (
<span className="cat" role="img">:cat:</span>
)
const DraggableMouse = withDrag(Mouse)
const DraggableCat = withDrag(Cat)
class App extends Component {
render = () => (
<Fragment>
<DraggableMouse />
<DraggableCat />
</Fragment>
)
}
接下来,让我们在高阶组件中增加 onDrag 回调函数,并在 props 中注入 x 和 y 的位置属性。
const withDrag = Wrapped => {
class WithDrag extends Component {
state = {
x: undefined,
y: undefined,
}
componentDidMount = () => new Draggable(this.ELEMENT, { onDrag: this.onDrag })
onDrag = e => {
const { x, y } = e.target.getBoundingClientRect();
this.setState({ x: Math.floor(x), y: Math.floor(y) })
}
render = () => (
<span className="draggable_wrapper" ref={e => (this.ELEMENT = e)}>
<Wrapped {...this.props} x={this.state.x} y={this.state.y} />
</span>
)
}
WithDrag.displayName = `WithDrag(${Wrapped.displayName || Wrapped.name})`
return WithDrag;
}
const Mouse = () => (
<span className="mouse" role="img">
:mouse:
{x !== undefined &&
y !== undefined && (
<span className="mouse__position"> {`(${x}, ${y})`} </span>
)}
</span>
)
现在 Mouse 组件会向用户展示他的 XY 位置属性
我们也可以给 HOC 传递 props 。然后在传递的过程中过滤掉这些无用的属性。举个例子,传递一个 onDrag 回调函数。
const withDrag = Wrapped => {
class WithDrag extends Component {
componentDidMount = () => new Draggable(this.ELEMENT, { onDrag: this.props.onDrag })
render = () => (
const { onDrag, ...passed } = this.props;
<span className="draggable__wrapper" ref={e => (this.ELEMENT = e)}>
<Wrapped {...passed} />
</span>
)
}
WithDrag.displayName = `WithDrag(${Wrapped.displayName || Wrapped.name})`
return WithDrag;
}
class App extends Component {
render = () => (
<Fragment>
<DraggableMouse
onDrag={e => console.info(e.target.getBoundingClientRect())}
/>
</Fragment>
)
}
通过使用 HOC ,我们的组件仍然很简单,复杂的逻辑都交给 HOC 来处理了。 我们的组件只关心传递给他们的内容。 我们可以在其他地方重复使用它们而且不会有可以被拖拽的属性。这使得我们的应用更容易维护。
优秀的实践 :+1:
- 当出现重复的模式的时候,使用它们
- 为了方便调试,需要更新处理之后组件的
displayName - 传递与当前
HOC无关的所有props
糟糕的实践 :-1:
render
译注:永远不要在 React render() 方法中定义 React 组件(甚至是无状态组件)。 React 在每次更新状态的时候,都会废弃旧的 html DOM 元素并将其替换为全新的元素。比如在 render() 函数中定义一个输入组件,元素被替换之后就会失去焦点,每次只能输入一个字符。
注意 :pray:
-
Refs不会被传递 - 务必复制静态方法
- 大部分
HOC都可以和render props相互替换使用
这就是一篇关于高阶组件的简短介绍 ~
本文已经联系原文作者,并授权翻译,转载请保留原文链接
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Don't Make Me Think
Steve Krug / New Riders Press / 18 August, 2005 / $35.00
Five years and more than 100,000 copies after it was first published, it's hard to imagine anyone working in Web design who hasn't read Steve Krug's "instant classic" on Web usability, but people are ......一起来看看 《Don't Make Me Think》 这本书的介绍吧!