我试图理解some code用ESnext编写的React(装饰器)。 我知道如何将装饰器从ESnext转换为ES6语法
// 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
// 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>,
));
}
}
答案 0 :(得分:1)
因为您有两个高阶组件(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)
或者(如果你没有使用redux)你可以将它们组合起来:
// 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))
答案 1 :(得分:1)
TypeScript文档提供了decorator composition的良好解释(TS装饰器和ES decorators proposal在大多数情况下是相同的):
当多个装饰器应用于单个声明时,它们的 评价类似于数学中的函数组成。在这 模型,当组成函数f和g时,得到的复合(f∘ g)(x)等于f(g(x))。
因此,在评估多个时执行以下步骤 TypeScript中单个声明的装饰器:
每个装饰器的表达式都是从上到下进行评估。
然后从下到上将结果称为函数。
所以它应该是:
export default DropTarget(ItemTypes.CARD, cardTarget, collectDrop)(
DragSource(ItemTypes.CARD, cardSource, collectDrag)(Card);
);
这应该用于学术目的,而不是用于生产。原始代码不是ES6而是JSX,它仍然需要将转换器(Babel)转换为有效的JavaScript。所以没有理由不使用Babel可以提供的所有功能,包括装饰器。