javascript - 如何处理 "polymorphic"函数组件

标签 javascript reactjs typescript

想象一下我正在编写一个 react 应用程序,用户可以在其中将不同颜色和大小的形状添加到某些“工作区”。假设我们有组件 CircleSquare,它们将具有不同的属性来定义它们。当用户添加形状时,其 Prop 将添加到工作区组件的状态中。然后工作区绘制如下形状:

import React, {useState} from "react";

interface ISquareProps {
    color: string;
    lineLength: number;
}

interface ICircleProps {
    color: string;
    radius: number;
}

const Square = ({lineLength}: ISquareProps) => (<div>I'm a square with line length {lineLength}</div>);
const Circle = ({radius}: ICircleProps) => (<div>I'm a circle with radius {radius}</div>);

const Workspace = () => {
    const [squares, setSquares] = useState(new Array<ISquareProps>());
    const [circles, setCircles] = useState(new Array<ICircleProps>());

    return (
        <>
            {squares.map((square) => <Square {...square} /> )}
            {circles.map((circle) => <Circle {...circle} /> )}
        </>
    );
};

在此处查找示例:

Edit draw-shapes-1

虽然这对于两种不同的形状效果很好,但如果我们有很多形状,就会变得很麻烦。

如果形状知道如何渲染自己怎么办?这个怎么样:

import React, {useState} from "react";

interface IShapeProps {
    color: string;
    render(): JSX.Element;
}

// ------- square -------
interface ISquareProps extends IShapeProps {
    lineLength: number;
}

const Square = ({lineLength}: ISquareProps) => (<div>I'm a square with line length {lineLength}</div>);

class SquareProps implements ISquareProps {
    public color: string;
    public lineLength: number;

    constructor(lineLength: number, color: string) {
        this.color = color;
        this.lineLength = lineLength;
    }

    public render() {
        return <Square {...this} />;
    }
}
// ------- circle -------
interface ICircleProps extends IShapeProps {
    radius: number;
}

const Circle = ({radius}: ICircleProps) => (<div>I'm a circle with radius {radius}</div>);

class CircleProps implements ICircleProps {
    public color: string;
    public radius: number;

    constructor(color: string, radius: number) {
        this.color = color;
        this.radius = radius;
    }

    public render() {
        return <Circle {...this} />;
    }
}
// ------- workspace -------
const Workspace = () => {
    const [shapes, setShapes] = useState(new Array<IShapeProps>());

    return (
        <>
            {shapes.map((shape) => shape.render() )}
        </>
    );
};

这里有一个工作示例:

Edit draw-shapes-2

这是用函数组件处理“多态”组件的可行方法吗? 是否应该考虑其他模式?

最佳答案

您似乎所做的只是柯里化(Currying) ShapeCircle 组件,但从我所看到的渲染方法中没有任何内容实际上告诉形状它是哪个形状是。 您需要该渲染函数的一个参数来决定它是哪一个。

您可以进行一些改进:

1)对我来说更有意义的事情是,不要只用一些“函数”来柯里化(Currying)它,而是将它包装在一个足够智能的 react 组件中来决定。

2)使用 props 而不是类属性,这就是它们的用途。没有理由将其重新分配给 this 变量

3) 使用条件 JSX 来决定根据 Prop 渲染哪个组件(您甚至可以切换形状,它们会随着新 Prop 触发重新渲染而切换)

4)我认为没有太多必要单独实现您拥有的 prop 接口(interface),您可以通过函数组件内联来实现


export const Shape = (props: IShapeProps) => {

    public render() {
        if (this.props.shapeType === 'Square') {
           return <Square lineheight={this.props.lineheight} color={this.props.color} />;
        } else {
           return <Circle radius={this.props.radius} color={this.props.color} />;
        }  
    }
}

关于javascript - 如何处理 "polymorphic"函数组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58984347/

相关文章:

javascript - JS数组中 "|"(管道)符号的用途是什么

JavaScript Canvas 沿 y 轴向上平移

Angular/Typescript 模型——如何组织

javascript - 将 CSS 对象转换为样式标签

android - 如何在 android 和 ios 上运行 angular 7 应用程序?

javascript - 谷歌地图,数组 + GLatLng + GPolyline

javascript - 如何从表单调用外部 javascript 方法?

reactjs - react , parent 在处理完成时通知 child

javascript - React native - 安装 native-base 后版本控制中包含哪些文件?

node.js - 在新的React版本中,如何修复TypeError : styled_components__WEBPACK_IMPORTED_MODULE_3__. default.dev?