主题样式组件

来自菜鸟教程
跳转至:导航、​搜索

💅 styled-components 是在 React 中处理 CSS 的好方法。 如果您不熟悉样式化组件,请查看我们的文章 styled-components,React 中处理 CSS 的现代方法以获取介绍。

在这篇文章中,我们将创建一个简单的电子邮件通讯订阅表单并使用 styled-components 来处理视觉外观。

使用 React 样板进行设置

我们将从设置 React Boilerplate 应用程序开始。 但是,如果您愿意,也可以使用 Create React App 开始。

查看 https://www.reactboilerplate.com/ 以获取此样板的详细说明。


要创建一个新项目,我们只需克隆样板 GitHub 存储库:

$ git clone --depth=1 https://github.com/react-boilerplate/react-boilerplate.git

我们删除示例应用程序以从头开始,然后启动应用程序:

$ npm run clean
$ npm start

编写示例表单

现在让我们构建电子邮件注册表单。 我们在它自己的组件中创建一个注册表单,使用 styled-components 很好地呈现它。

让我们创建四个样式组件:FormTitleButtonInput

每个组件代表我们表单的一小部分,我们为每个组件添加一些 CSS 规则:

组件/SignupForm/index.js

import React from 'react';
import styled from 'styled-components';

const Form = styled.form`
  margin: 0 auto;
  width: 50%;
  min-width: 400px;
  max-width: 800px;
  text-align: center;
  border: 1px solid #ddd;
  padding-top: 0px;
  padding-bottom: 90px;
  color: black;
  background: white;
`;

const Title = styled.h2`
  margin-top: 40px;
  margin-bottom: 70px;
  font-size: 1.5em;
  color: black;
  background-color: white;
`;

const Button = styled.button`
  font-size: 1.5em;
  background-color: black;
  color: white;
`;

const Input = styled.input`
  font-size: 1.45em;
  border: 1px solid #ddd;
`;

然后我们创建一个简单的组件,用一个简单的 console.log() 处理提交事件,打印出给定的电子邮件,因为我们只想专注于样式部分:

import React from 'react';

export default class SignupForm extends React.Component {

  signUp = (e) => {
    const email = new FormData(e.target).get('email');
    e.preventDefault();
    console.log(`New signup from ${email}`);
  }

  render() {
    return (
      <Form onSubmit={this.signUp}>
        <Title>
          Sign up to my newsletter
        </Title>
        <Input type="email" name="email" />
        <Button>Sign up</Button>
      </Form>
    );
  }
}

接下来,我们将它导入到 React Boilerplate 为我们创建的 HomePage 组件中,然后渲染 <SignupForm />

容器/主页/index.js

import React from 'react';
import SignupForm from '../../components/SignupForm';

export default class HomePage extends React.Component {
  render() {
    return (
      <SignupForm />
    );
  }
}

就是这样,表单现在应该在我们的应用程序中很好地显示:

在 CSS 中,我们有一些不同的属性被不同的组件使用:背景和前景色、边框颜色和文本颜色。

他们现在有固定的颜色,因为我们只有一个页面上的表单,但是要求发生了变化,现在我们被告知必须将表单添加到具有不同背景和配色方案的各种页面中。

我们需要使组件可重用,我们可以使用 主题 来实现。

创建主题

通过将我们所有的组件包装在 ThemeProvider 包装器组件中,并通过在我们的 styled-components CSS 中引用 props.theme 的属性来创建主题:

import React from 'react';
import styled, { ThemeProvider } from 'styled-components';

const Form = styled.form`
  /* other properties */
  border: 1px solid ${(props) => props.theme.borderColor};
  color: ${(props) => props.theme.primaryColor};
  background-color: ${(props) => props.theme.secondaryColor};
`;

const Title = styled.h2`
  /* other properties */
  background-color: ${(props) => props.theme.secondaryColor};
  color: ${(props) => props.theme.primaryColor};
`;

const Button = styled.button`
  /* other properties */
  background-color: ${(props) => props.theme.primaryColor};
  color: ${(props) => props.theme.secondaryColor};
`;

const Input = styled.input`
  /* other properties */
  border: 1px solid ${(props) => props.theme.borderColor};
`;

我们创建了一个主题对象,它是一个对象字面量,具有我们在样式组件中引用的属性:

const theme = {
  secondaryColor: 'white',
  primaryColor: 'black',
  borderColor: '#ccc',
};

最后我们将 Form 组件包装在 ThemeProvider 包装器组件中:

export default class SignupForm extends React.Component {

  /* ... */

  render() {
    return (
      <ThemeProvider theme={theme}>
        <Form onSubmit={this.signUp}>
          <Title>
            Sign up to my newsletter
          </Title>
          <Input type="email" name="email" />
          <Button>Sign up</Button>
        </Form>
      </ThemeProvider>
    );
  }
}

这是使用样式组件进行主题化的基本方法。 我们将所有主题样式放在 theme 对象中,所有组件都使用这些样式。

创建可重用的主题

我们现在将两次添加注册表单到一个页面。 第一次页面背景是亮的,第二次是暗的。

我们将一些简单的 CSS 规则添加到 app/global-styles.css 中,这是一个由 React Boilerplate 自动包含的文件:

.container.dark {
  background: #282828;
}

我们可以将 SignupForm 组件包装在使用 container 类的类中,而 dark 类的存在会使其变暗。

容器/主页/index.js

import React from 'react';
import SignupForm from '../../components/SignupForm';

export default class HomePage extends React.Component {
  render() {
    return (
      <main>
        <div className="container">
          <SignupForm />
        </div>
        <div className="container dark">
          <SignupForm />
        </div>
      </main>
    );
  }
}

如果我们希望第二种形式在黑暗的背景中很好地融合,而不是像大拇指一样突出怎么办? 我们在 HomePage 组件的 render() 方法中的 SignupForm 上添加一个 dark 属性:

return (
  <main>
    <div className="container bright">
      <SignupForm />
    </div>
    <div className="container dark">
      <SignupForm dark />
    </div>
  </main>
);

我们在 SignupForm 组件的 constructor() 方法中寻找它的道具,如果存在,我们使用深色主题:

export default class SignupForm extends React.Component {

  constructor(props) {
    super(props);

    this.theme = {
      secondaryColor: 'white',
      primaryColor: '#282828',
      borderColor: '#ccc',
    };

    if (props.dark) {
      this.theme.secondaryColor = '#282828';
      this.theme.primaryColor = '#fff';
    }
  }

  /* ... */

  render() {
    return (
      <ThemeProvider theme={this.theme}>
        <Form onSubmit={this.signUp}>
          <Title>
            Sign up to my newsletter
          </Title>
          <Input type="email" name="email" />
          <Button>Sign up</Button>
        </Form>
      </ThemeProvider>
    );
  }
}

我们现在得到了我们想要的结果,更适合深色背景:



这种方法允许我们通过创建属性约定和根据我们需要的样式编辑主题来玩不同的演示文稿。