干掉反应代码。更改父组件背景的多个按钮组件



我相信有一种方法可以干燥代码。changeColor(( 所做的只是更改父组件的背景颜色。

import { Play } from "./play";
import { Hello } from "./hello";
import { styles } from "./styles";`
export class Buttons extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            color: styles.container
        };
        this.changeColor = this.changeColor.bind(this);
        this.changeColor1 = this.changeColor1.bind(this);
        this.changeColor2 = this.changeColor2.bind(this);
    }
    changeColor(newColor) {
        this.setState({
            color: styles.backPlay
        });
    }
    changeColor1(newColor) {
        this.setState({
            color: styles.backTime
        });
    }
    changeColor2(newColor) {
        this.setState({
            color: styles.backHello
        });
    }
    render() {
        return (
            <div style={this.state.color}>
                <Play onClick={this.changeColor} />
                <Time onClick={this.changeColor1} />
                <Hello onClick={this.changeColor2} />
            </div>
        );
    }
}

这是样式页面,我也认为可以使用一点 DRY。Container、backPlay、backTime 和 backHello 都表示相同的容器,但背景不同。

样式.js

export var styles = {
    loc: {
        padding: 25,
        margin: 40,
        fontWeight: "bold",
        textAlign: "center"
    },
    green: {
        color: "green",
        background: "#59D13E"
    },
    red: {
        color: "yellow",
        background: "#A9A81D"
    },
    blue: {
        color: "blue",
        background: "#34BEE3"
    },
    container: {
        display: "inline-block",
        textAlign: "center",
        marginTop: 50,
        padding: 40
    },
    backPlay: {
        display: "inline-block",
        textAlign: "center",
        background: "yellow",
        marginTop: 50,
        padding: 40
    },
    backTime: {
        display: "inline-block",
        textAlign: "center",
        background: "blue",
        marginTop: 50,
        padding: 40
    },
    backHello: {
        display: "inline-block",
        textAlign: "center",
        background: "green",
        marginTop: 50,
        padding: 40
    },
    mainCont: {
        height: "100vh",
        textAlign: "center",
        background: "#FFA692"
    }
};

更新

我找到了一种更好的方法来干掉这段代码。通过使用一个按钮组件并操作其状态。让我知道是否有更好的方法可以做到这一点。

按钮容器.js

import React from 'react'
import Button from './Button'
export default class ButtonContainer extends React.Component {
    state = {
        colors: ['red', 'blue', 'green']
    }
    toggleClass = (color, id) => {
        let colors = [...this.state.colors]
        const newColors = colors.map((newColor, index) => {
            if (id === index) {
                const copyMap = { 0: 'red', 1: 'blue', 2: 'green' }
                const copy = color === 'not' ? copyMap[index] : 'not'
                return copy
            } else {
                return newColor
            }
        })
        this.setState({ colors: newColors })
    }
    render() {
        return (
            <div className='button-container'>
                {this.state.colors.map((color, index) =>
                    <Button
                        toggleClass={this.toggleClass}
                        key={index}
                        id={index}
                        name={color}
                    />
                )}
            </div>
        )
    }
}

按钮.js

import React from 'react'
const Button = (props) => (
    <button
        className={`button-component ${props.name}`}
        onClick={() => props.toggleClass(props.name, props.id)}
    >
        {props.name}
    </button>
)
export default Button

_button-container.scss

.button-container {
    margin: 10rem auto;
    text-align: center;
}

_button.scss

.button-component {
    padding: 4rem;
    margin: 0 2rem;
}
.red {
    background: red;
}
.blue {
    background: blue;
}
.green {
    background: green;
}
.not {
    background: none;
}

您可以使用.bind()将参数预先绑定到函数,然后再将其作为 prop 传递:

export class Buttons extends React.Component {
    state = {
        color: styles.container
    };
    changeColor = newColor => {
        this.setState({
            color: newColor
        });
    };
    render() {
        return (
            <div style={this.state.color}>
                <Play onClick={this.changeColor.bind(this, styles.backPlay)} />
                <Time onClick={this.changeColor.bind(this, styles.backTime)} />
                <Hello onClick={this.changeColor.bind(this, styles.backHello)} />
            </div>
        );
    }
}

还可以删除构造函数并使用胖箭头函数将方法自动绑定到组件。

样式.js

const container = {
    display: "inline-block",
    textAlign: "center",
    marginTop: 50,
    padding: 40
};
export const styles = {
    loc: {
        padding: 25,
        margin: 40,
        fontWeight: "bold",
        textAlign: "center"
    },
    green: {
        color: "green",
        background: "#59D13E"
    },
    red: {
        color: "yellow",
        background: "#A9A81D"
    },
    blue: {
        color: "blue",
        background: "#34BEE3"
    },
    container,
    backPlay: {
        ...container,
        background: "yellow"
    },
    backTime: {
        ...container,
        background: "blue"
    },
    backHello: {
        ...container,
        background: "green"
    },
    mainCont: {
        height: "100vh",
        textAlign: "center",
        background: "#FFA692"
    }
};

可以使用 es6 spread 运算符将styles.container的内容复制到每个样式,然后重写 color 属性。

由于所有变色函数都非常相似,因此您可以传入要应用的样式的名称并在函数中使用它,从而节省重复。

changeColor(attr) {
    this.setState({
        color: styles[attr]
    });
}
render() {
    return (
        <div style={this.state.color}>
            <Play onClick={() => this.changeColor('backPlay')} />
            <Time onClick={() => this.changeColor('backTime')} />
            <Hello onClick={() => this.changeColor('backHello')} />
        </div>
    );
}

最新更新