使用AntDesign在React中制作漂亮的UI

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

Ant Design 是一个 React UI 库,其中包含大量易于使用的组件,可用于构建优雅的用户界面。

Ant Design 由中国企业集团阿里巴巴创建,被多家知名企业使用:阿里巴巴(当然)、腾讯、百度等。 虽然 Material-UI 仍然是最受欢迎的 React UI 库,在 Github 上拥有超过 4 万颗星,但 Ant Design 目前紧随其后,并且正在迅速缩小差距。

Ant Design 还有一个移动版,你可以在这里了解更多。

入门

在本教程中,我们将构建一个基本的 todo 应用程序来展示一些 Ant Design 的组件。 我们的第一步将是设置我们的样板。 我已经使用 create-react-app 完成了。

然后我们需要将 antd 依赖添加到项目中:

$ yarn add antd

# or, using npm:
$ npm install antd --save

在我们开始构建我们的 <Todo /> 组件之前,我们将在根组件中添加对它的引用:

index.js

import React from "react";
import ReactDOM from "react-dom";
import Todo from "./todo";

import "./styles.css";

function App() {
  return (
    <div className="App">
      <Todo />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

构建 Todo 组件

现在我们可以开始构建我们的 <Todo /> 组件。 打开一个名为 todo.js 的新文件,其内容如下:

todo.js

import React from "react";

export default class Todo extends React.Component {
  render() {
    return (
      <div className="todoContainer">
        <h1>TODO App</h1>
      </div>
    );
  }
}

我将编辑样式表,以便 .todoContainer 很好地位于页面中心。

样式.css

.App {
  font-family: sans-serif;
  text-align: center;
}

.todoContainer {
  width: 75%;
  margin-left: auto;
  margin-right: auto;
}

凉爽的! 现在让我们为 <Todo /> 组件添加一个输入。 我们将使用 antd 提供的那个,确保同时导入库的 CSS 文件。

todo.js

import React from "react";
import { Input } from "antd";

// Don't forget to include the CSS styles for antd!
import "antd/dist/antd.css";

export default class Todo extends React.Component {
  render() {
    return (
      <div className="todoContainer" />
        <h1>TODO App</h1>

        <Input
          placeholder="What needs to be done?"
        />
      </div>
    );
  }
}

太好了,现在我们正在渲染一个文本输入框。 但是,它什么也没做。 我们需要我们的输入将其内容添加到组件的状态中,以便我们可以呈现待办事项列表。 我们将使用 <Input /> 上的 onPressEnter 属性来检测用户何时提交新的待办事项:

todo.js

// --- snip ---

export default class Todo extends React.Component {
  constructor() {
    super();

    // Initialize the state
    this.state = {
      todos: []
    };
  }

  handlePressEnter = e => {
    // Create a todo object containing its index and content
    const todo = {
      index: this.state.todos.length,
      content: e.target.value
    };

    // Add the todo to our array
    const newTodos = this.state.todos.concat(todo);

    this.setState({
      todos: newTodos
    });

    // Clear input
    e.target.value = "";
  };

  render() {
    return (
      <div className="todoContainer">
        <h1>TODO App</h1>

        <Input
          placeholder="What needs to be done?"
          onPressEnter={this.handlePressEnter}
        />
      </div>
    );
  }
}

现在 handlePressEnter() 将在用户输入新的待办事项时更新组件的状态,但我们仍然必须渲染它们。

为此,我们可以使用 Ant Design 的 <List /> 组件。 它接收一个数组作为它的 dataSource 属性,并根据传递给它的 renderItem 属性的任何函数来渲染它。

todo.js

import React from "react";
import { Input, List } from "antd";

import "antd/dist/antd.css";

export default class Todo extends React.Component {
  // --- snip ---

  render() {
    return (
      <div className="todoContainer">
        <h1>TODO App</h1>

        <Input
          placeholder="What needs to be done?"
          onPressEnter={this.handlePressEnter}
        />

        <List
          {/* emptyText sets the text to display in an empty list */}
          locale={{ emptyText: "No todo items" }}
          dataSource={this.state.todos}
          renderItem={item => (
            <List.Item>{item.content}</List.Item>
          )}
        />
      </div>
    );
  }
}

达达! 现在我们的基本待办事项应用程序正在运行! 但是,我们还可以做更多的事情来让它变得更好!

变得花哨

我们的 todo 应用程序已启动并正在运行。 但是,我们还需要添加更多内容:最重要的是,删除按钮。 我们还将添加一个日期选择器,因为为什么不呢?

为了避免使我们的 <Todo /> 过于复杂,我将把 <List.Item /> 提取到它自己的单独组件中。 我还将定义一个新方法 removeTodo() 来删除给定索引的待办事项。 然后我将该方法传递给我们的新组件。

作为移除按钮,我们可以使用 Ant 的 <Icon /> 组件。 将其添加到 <List.Item />'s action 属性中,该属性采用组件数组。 要查看完整的图标列表,请参阅 Ant Design 网站上的 此页面

todo.js

import React from "react";
import { Input, List, Icon } from "antd";

import "antd/dist/antd.css";

export default class Todo extends React.Component {
  // --- snip ---

  removeTodo = index => {
    let newTodos = [...this.state.todos];

    // Remove element
    newTodos.splice(index, 1);

    // Decrement greater indexes
    for (let i = index; i < newTodos.length; i++) {
      newTodos[i].index -= 1;
    }

    // Update state
    this.setState({
      todos: newTodos
    });
  };

  render() {
    return (
      <div className="todoContainer">
        <h1>TODO App</h1>

        <Input
          placeholder="What needs to be done?"
          onPressEnter={this.handlePressEnter}
        />

        <List
          locale={{ emptyText: "No todo items" }}
          dataSource={this.state.todos}
          renderItem={item => (
            <TodoItem
              todo={item}
              removeTodo={this.removeTodo}
            />
          )}
        />
      </div>
    );
  }
}

class TodoItem extends React.Component {
  remove = () => {
    // Remove this TodoItem
    this.props.removeTodo(this.props.todo.index);
  };

  render() {
    return (
      <List.Item
        actions={[
          <Icon
            type="close-circle"
            theme="filled"
            onClick={this.remove}
          />
        ]}
      >
        {this.props.todo.content}
      </List.Item>
    );
  }
}

伟大的! 现在剩下的就是添加 Ant 的 <DatePicker /> 组件。 为此,我们将通过将 datedateString 属性添加到我们存储在状态中的 todo 对象来更新 handlePressEnter() 方法。 然后我们需要一个额外的方法,setDate(),来更新这些属性。

todo.js

import React from "react";
import { Input, List, Icon, DatePicker } from "antd";

import "antd/dist/antd.css";

export default class Todo extends React.Component {
  // --- snip ---

  handlePressEnter = e => {
    // Create a todo object containing its index, content,
    // as well as an empty date
    const todo = {
      index: this.state.todos.length,
      content: e.target.value,
      date: null,
      dateString: ""
    };

    // Add the new todo to our array
    const newTodos = this.state.todos.concat(todo);

    this.setState({
      todos: newTodos
    });

    // Clear input
    e.target.value = "";
  };

  setDate = (index, date, dateString) => {
    // Set the date of the given todo
    let newTodos = [...this.state.todos];
    newTodos[index].date = date;
    newTodos[index].dateString = dateString;

    // Initialize the state
    this.setState({
      todos: newTodos
    });
  };

  render() {
    return (
      <div className="todoContainer">
        <h1>TODO App</h1>

        <Input
          placeholder="What needs to be done?"
          onPressEnter={this.handlePressEnter}
        />

        <List
          locale={{ emptyText: "No todo items" }}
          dataSource={this.state.todos}
          renderItem={item => (
            <TodoItem
              todo={item}
              removeTodo={this.removeTodo}
              setDate={this.setDate}
            />
          )}
        />
      </div>
    );
  }
}

class TodoItem extends React.Component {
  remove = () => {
    // Remove this TodoItem
    this.props.removeTodo(this.props.todo.index);
  };

  handleDateChange = (date, dateString) => {
    // Update the date when changed
    this.props.setDate(this.props.todo.index, date, dateString);
  }

  render() {
    return (
      <List.Item
        actions={[
          <DatePicker
            format="MM/DD/YYYY"
            onChange={this.handleDateChange}
            value={this.props.todo.date}
          />,
          <Icon
            type="close-circle"
            theme="filled"
            onClick={this.remove}
          />
        ]}
      >
        {this.props.todo.content}
      </List.Item>
    );
  }
}

瞧! 🎉

我们现在有了使用 Ant Design 的全功能待办事项应用程序! 如果您想了解更多关于 Ant 的信息,请查看 他们的文档

您可以在 CodeSandbox 上找到这篇文章的完整代码。