在我读到mixins有多糟糕,并且自己经历了一些糟糕的经历之后,我想重构我的代码,使用组合而不是mixins来实现可重用性。
我想要一个组件来发出事件,并成为样式。所以我有了mixins和EventEmitter,前者包含操纵事件的函数,后者包含操纵样式的函数。
var Styleable = {
addStyleProperty: function(styleProperty) {
...
},
...
};
var EventEmitter = {
addEventListener: function(eventName, func) {
},
...
};使用mixins时,示例组件如下所示:
var Button = React.createClass({
mixins = [EventEmitter, Styleable],
...
});通过组合,我尝试为Styleable和EventEmitter创建组件,如下所示:
var StylableComponent = React.createClass({
addStyleProperty: ...
render: function() {
React.createElement(this.props.wrappedComponent, ...)??
}
}
var EventEmitterComponent = ...但我不知道如何正确使用它们。我读到我必须使用这些组件作为包装器,但我不知道如何实现这一点。我试着像上面例子中的render函数那样做。如何实例化一个按钮,它的功能就像mixin变量一样?所以我只需要像这样传递所需的函数:
<Button is={[StyleableComponent, EventEmitterComponent]}/> 或者我期望从组合中得到一个错误的行为?
发布于 2016-10-15 21:33:56
从本质上讲,您希望创建一个返回全新组件的函数。
例如,对于你的EventEmitter,它看起来像这样:
import eventEmitter from 'your-event-emitter-location';
// This function takes a component as an argument, and returns a component.
function eventEmitterWrapper(ComposedComponent) {
// This is the brand new "wrapper" component we're creating:
return class extends Component {
render() {
// We want to return the supplied component, with all of its supplied
// props, but we also want to "add in" our additional behaviour.
return (
<ComposedComponent
{...this.props}
eventEmitter={eventEmitter}
/>
);
}
}
}
要使用它,您可以这样做:
import Button from '../Button';
import eventEmitterWrapper from '../../HOCs/event-emitter';
class Home extends Component {
render() {
const EventEmitterButton = eventEmitterWrapper(Button);
return (
<div>
<EventEmitterButton onClick={doSomething}>
Hello there!
</EventEmitterButton>
</div>
)
}
}
最后,在你的按钮中,你可以从道具中访问事件发射器:
const Button = ({ children, onClick, eventEmitter }) => {
// Let's say, for example, you want to emit an event whenever the
// button is clicked. You could do something like this:
const clickHandler = (ev) => {
onClick(ev);
if (eventEmitter) {
eventEmitter.emit('click', ev);
}
};
return (
<button onClick={clickHandler}>
{children}
<button>
)
}
注释:这是一个人为的例子。这个模式对我来说有点难闻;Button太了解事件发射器的内部工作方式(例如,它不需要知道它有一个emit方法。如果你改变了你的事件发射器的工作方式,你将有一堆“哑巴”组件需要更新)。
要解决这个问题,我需要更多地了解您的用例,但我可能会让eventEmitterWrapper函数返回的类公开简单、特定的方法(比如"emitEvent",它只接受鼠标/键盘事件的一个参数)
希望它能说明如何使用高阶组件!
其他阅读:
https://stackoverflow.com/questions/40058413
复制相似问题