首页 > 解决方案 > 如何使用 React 中的 CSS 模块以多种方式设置同一个组件的样式?

问题描述

我最近刚刚在我的项目中切换到使用 CSS 模块并且遇到了一些问题。

在下面的简单代码示例中,我正在创建一个输入组件,我希望在创建表单时能够将其用作表单字段。当我希望能够在某些情况下以不同的方式设置输入组件的样式时,问题就出现了。

FormInput.js

const FormInput = props => (
  <FormControl>
    <InputLabel>{props.label}</InputLabel>
    <Input />
  </FormControl>
);

Form.js

import React from 'react';
import Button from '@material-ui/core/Button';
import Input from './input';

const Form = () => (
  <form>
    <Input label="Name" />
    <Button> Submit </Button>
  </form>
);

我知道这可以使用样式组件来完成,但我真的在寻找使用 CSS 模块的解决方案。任何帮助,将不胜感激

标签: reactjsstyled-componentsreact-propscss-modulesreact-css-modules

解决方案


您可以简单地导入 css 并将其作为propto传递Input。在这种情况下,您可以将其作为className.

注意:正如您将在下面注意到的那样,CSS在样式嵌套和伪元素方面可能有点多余,这就是为什么我强烈推荐SASS (scssless) 用于预处理样式表(后处理会将SASS样式表转换为普通样式表)CSS样式表给你)。

工作示例(重用Input但使用不同的样式classes):

编辑 React CSS 模块


组件/输入(它接受className字符串、onChange函数(必需)、label字符串、name字符串(必需)和value字符串)

import React from "react";
import PropTypes from "prop-types";

const Input = ({ className, onChange, label, name, value }) => (
  <div className={className}>
    <label htmlFor={name}>{label}: </label>
    <input value={value} onChange={onChange} name={name} type="text" />
  </div>
);

// PropTypes ensures that passed down props adhere to the type checking
// rules defined below
Input.propTypes = {
  className: PropTypes.string,
  onChange: PropTypes.func.isRequired,
  label: PropTypes.string,
  name: PropTypes.string.isRequired,
  value: PropTypes.string
};

export default Input;

styles.css(你需要使用camelCase而不是snake-casefor classNames)

.appContainer {
  text-align: center;
  padding: 20px;
}

input {
  height: 40px;
  vertical-align: middle;
  display: inline-block;
  border: 0 none;
  padding: 0 10px;
  background: #fff;
  color: #666;
  border: 1px solid #e5e5e5;
  transition: 0.2s ease-in-out;
  transition-property: color, background-color, border;
  font-size: 15px;
}

.nameField {
  font-weight: bold;
  color: blue;
  margin-bottom: 20px;
}

.nameField > input {
  color: green;
}

.emailField {
  font-weight: bold;
  color: red;
  margin-bottom: 20px;
}

.emailField > input {
  color: blue;
}

.resetButton {
  cursor: pointer;
  background-color: transparent;
  color: #222;
  border: 1px solid #e5e5e5;
  margin: 0;
  overflow: visible;
  box-sizing: border-box;
  padding: 0 30px;
  vertical-align: middle;
  font-size: 14px;
  line-height: 38px;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  transition: 0.1s ease-in-out;
  transition-property: color, background-color, border-color;
}

.resetButton:hover {
  background-color: transparent;
  color: #222;
  border-color: #b2b2b2;
}

.resetButton:focus {
  outline: none;
}

components/Appimport所有的cssasclasses并根据需要应用它们——你也可以使用ES6 解构来提取单个类,例如 import { appContainer } from "./styles.css";:)

import React from "react";
import { render } from "react-dom";
import Input from "./components/Input";
import useFieldHandler from "./hooks/useFieldHandler";
import classes from "./styles.css";

const App = () => {
  const { values, handleChange, resetValues } = useFieldHandler({
    name: "",
    email: ""
  });

  return (
    <div className={classes.appContainer}>
      <h1>CSS Modules</h1>
      <Input
        label="Name"
        name="name"
        className={classes.nameField}
        value={values.name}
        onChange={handleChange}
      />
      <Input
        label="Email"
        name="email"
        className={classes.emailField}
        value={values.email}
        onChange={handleChange}
      />
      <div className={classes.btnContainer}>
        <button
          type="button"
          className={classes.resetButton}
          onClick={resetValues}
        >
          Reset
        </button>
      </div>
    </div>
  );
};

render(<App />, document.getElementById("root"));

推荐阅读