首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React mixin to composition

React mixin to composition
EN

Stack Overflow用户
提问于 2016-10-15 19:24:42
回答 1查看 220关注 0票数 0

在我读到mixins有多糟糕,并且自己经历了一些糟糕的经历之后,我想重构我的代码,使用组合而不是mixins来实现可重用性。

我想要一个组件来发出事件,并成为样式。所以我有了mixins和EventEmitter,前者包含操纵事件的函数,后者包含操纵样式的函数。

代码语言:javascript
复制
var Styleable = {
  addStyleProperty: function(styleProperty) {
     ...
  },
  ... 
};
var EventEmitter = {
   addEventListener: function(eventName, func) {
   },
   ...
};

使用mixins时,示例组件如下所示:

代码语言:javascript
复制
var Button = React.createClass({
  mixins = [EventEmitter, Styleable],
  ...
});

通过组合,我尝试为Styleable和EventEmitter创建组件,如下所示:

代码语言:javascript
复制
var StylableComponent = React.createClass({
  addStyleProperty: ...
  render: function() {
    React.createElement(this.props.wrappedComponent, ...)??
  }
}
var EventEmitterComponent = ...

但我不知道如何正确使用它们。我读到我必须使用这些组件作为包装器,但我不知道如何实现这一点。我试着像上面例子中的render函数那样做。如何实例化一个按钮,它的功能就像mixin变量一样?所以我只需要像这样传递所需的函数:

代码语言:javascript
复制
<Button is={[StyleableComponent, EventEmitterComponent]}/> 

或者我期望从组合中得到一个错误的行为?

EN

回答 1

Stack Overflow用户

发布于 2016-10-15 21:33:56

从本质上讲,您希望创建一个返回全新组件的函数。

例如,对于你的EventEmitter,它看起来像这样:

代码语言:javascript
复制
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}
        />
      );
    }
  }
}

要使用它,您可以这样做:

代码语言:javascript
复制
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>
    )
  }
}

最后,在你的按钮中,你可以从道具中访问事件发射器:

代码语言:javascript
复制
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",它只接受鼠标/键盘事件的一个参数)

希望它能说明如何使用高阶组件!

其他阅读:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40058413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档