代码之家  ›  专栏  ›  技术社区  ›  Manuk Karapetyan

如何将decorator语法转换为ES6?

  •  2
  • Manuk Karapetyan  · 技术社区  · 7 年前

    我在努力理解 some code 用ESnext(装饰器)编写的React。

    // ESnext
    function collect(connect, monitor) {
      return {
        connectDragSource: connect.dragSource(),
        isDragging: monitor.isDragging()
      }
    }
    
    @DragSource(Types.CARD, cardSource, collect)
    export default class Card extends React.Component {
      render() {
        const { id } = this.props;
        const { isDragging, connectDragSource } = this.props;
    
        return connectDragSource(
          <div>
            I am a draggable card number {id}
            {isDragging && ' (and I am being dragged now)'}
          </div>
        );
      }
    }
    

    // ES6
    function collect(connect, monitor) {
      return {
        connectDragSource: connect.dragSource(),
        isDragging: monitor.isDragging()
      };
    }
    
    class Card extends React.Component {
      render() {
        const { id } = this.props;
        const { isDragging, connectDragSource } = this.props;
    
        return connectDragSource(
          <div>
            I am a draggable card number {id}
            {isDragging && ' (and I am being dragged now)'}
          </div>
        );
      }
    }
    
    export default DragSource(Types.CARD, cardSource, collect)(Card);
    

    但是我被困在如何将代码转换成ES6?

    function collectDrop(connect) {
      return {
        connectDropTarget: connect.dropTarget(),
      };
    }
    
    function collectDrag(connect, monitor) {
      return {
        connectDragSource: connect.dragSource(),
        isDragging: monitor.isDragging()
      };
    }
    
    @DropTarget(ItemTypes.CARD, cardTarget, collectDrop)
    @DragSource(ItemTypes.CARD, cardSource, collectDrag)
    export default class Card extends Component {
      static propTypes = {
        connectDragSource: PropTypes.func.isRequired,
        connectDropTarget: PropTypes.func.isRequired,
        index: PropTypes.number.isRequired,
        isDragging: PropTypes.bool.isRequired,
        id: PropTypes.any.isRequired,
        text: PropTypes.string.isRequired,
        moveCard: PropTypes.func.isRequired,
      };
    
      render() {
        const { text, isDragging, connectDragSource, connectDropTarget } = this.props;
        const opacity = isDragging ? 0 : 1;
    
        return connectDragSource(connectDropTarget(
          <div style={{ ...style, opacity }}>
            {text}
          </div>,
        ));
      }
    }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   lukaleli    7 年前

    因为您有两个高阶组件(HOC)装饰器,所以在使用这两个(DropTarget和DragSource)导出时,您需要将它们组合起来并包装您的类。如果您正在使用 redux compose 它结合了多个HOC并用它包装了类。您需要关注的代码位于以下代码的末尾:

    import { compose } from 'redux'
    
    function collectDrop(connect) {
      return {
        connectDropTarget: connect.dropTarget(),
      };
    }
    
    function collectDrag(connect, monitor) {
      return {
        connectDragSource: connect.dragSource(),
        isDragging: monitor.isDragging()
      };
    }
    
    class Card extends Component {
      static propTypes = {
        connectDragSource: PropTypes.func.isRequired,
        connectDropTarget: PropTypes.func.isRequired,
        index: PropTypes.number.isRequired,
        isDragging: PropTypes.bool.isRequired,
        id: PropTypes.any.isRequired,
        text: PropTypes.string.isRequired,
        moveCard: PropTypes.func.isRequired,
      };
    
      render() {
        const { text, isDragging, connectDragSource, connectDropTarget } = this.props;
        const opacity = isDragging ? 0 : 1;
    
        return connectDragSource(connectDropTarget(
          <div style={{ ...style, opacity }}>
            {text}
          </div>,
        ));
      }
    }
    
    const enhance = compose(
      DropTarget(ItemTypes.CARD, cardTarget, collectDrop),
      DragSource(ItemTypes.CARD, cardSource, collectDrag)
    )
    
    export default enhance(Card)
    

    // Comment this part out
    /* const enhance = compose(
      DropTarget(ItemTypes.CARD, cardTarget, collectDrop),
      DragSource(ItemTypes.CARD, cardSource, collectDrag)
    )
    
    export default enhance(Card)*/
    
    // and change to this
    
    const dropTargetHOC = DropTarget(ItemTypes.CARD, cardTarget, collectDrop)
    const dragSourceHOC = DragSource(ItemTypes.CARD, cardSource, collectDrag)
    
    export default dropTargetHOC(dragSourceHOC(Card))
    
        2
  •  1
  •   Estus Flask    7 年前

    TypeScript文档很好地解释了 decorator composition (TS装饰器和 ES decorators proposal 大部分相同):

    评价类似于数学中的函数合成。在这个 模型,当组合函数f和g时,得到的组合(f

    因此,在评估多个 TypeScript中单个声明上的装饰器:

    每个装饰器的表达式从上到下求值。

    然后将结果从下到上称为函数。

    export default DropTarget(ItemTypes.CARD, cardTarget, collectDrop)(
      DragSource(ItemTypes.CARD, cardSource, collectDrag)(Card);
    );
    

    这应该用于学术目的,而不是用于生产。原始代码不是ES6而是JSX,它仍然需要一个transpiler(Babel)来转换为有效的JavaScript。因此,没有理由不使用巴贝尔提供的所有功能,包括装饰器。