React入门Demo

1,160 阅读6分钟

我正在参与掘金创作者训练营第6期,点击了解活动详情

目标

使用React.js库,结合ant-designUI组件库,实现一个表单添加,列表展示,支持搜索和分页的demo。

背景概况

React是用于构建用户界面JavaScript库, 起源于Facebook的内部项目,于2013年5月开源。

React是什么

React 不是一个 MVC 框架。React 是一个用于构建可组合用户界面的库。 React主要用于构建UI。它鼓励创建那些用于呈现随时间变化数据的、可复用的 UI 组件。

React官网

特点

  1. 声明式设计:React 使创建交互式 UI 变得轻而易举。为你应用的每一个状态设计简洁的视图,当数据变动时 React能高效更新并渲染合适的组件。
  2. 组件化: 构建管理自身状态的封装组件,然后对其组合以构成复杂的 UI。
  3. 高效:React通过对DOM的模拟,最大限度地减少与DOM的交互。
  4. 灵活:无论你现在使用什么技术栈,在无需重写现有代码的前提下,通过引入React来开发新功能。

为什么使用React

  1. 使用组件化开发方式,符合现代Web开发的趋势。
  2. 技术成熟,社区完善,配件齐全,适用于大型Web项目(生态系统健全)。
  3. 由Facebook专门的团队维护,技术支持可靠。
  4. ReactNative - Learn once, write anywhere: Build mobile apps with React。
  5. 使用方式简单,性能非常高,支持服务端渲染。
  6. React非常火,从技术角度,可以满足好奇心,提高技术水平;从职业角度,有利于求职和晋升,有利于参与潜力大的项目。

基本使用

安装

安装node,参考之前的教程就好。戳这里

创建项目

创建新的 React 应用。产用官方推荐的 Create React App。 我在这里还搜集了其他创建项目的方法:如何从零开始创建React项目

Create React App

Create React App 全局安装 npm install -g create-react-app

以下三种选择其中的一种即可。我选择的yarn安装。

npx create-react-app my-app
npm init react-app my-app
yarn create react-app my-app

注意

  1. 如果安装报错,有可能是npm源的问题。修改源即可。戳这里解决
  2. 安装完成之后,运行 yarn start。点击链接,出现如下界面,恭喜你,第一个React项目创建好了。

image.png image.png

组件

React 组件可以让你把UI分割为独立、可复用的片段,并将每一片段视为相互独立的部分。 组件可以理解为,根据业务拆分出来,一块单独的功能模块。包括模板【html】、属性【props】和事件【通信】。

创建组件的两种方式 戳这里

  1. 函数组件(无状态组件)

  2. function Welcome(props) {
    return <h1>Hello, {props.name}</h1>;
    }
    
  3. class组件(有状态组件)

  4. class Welcome extends React.Component {
         render() {
           return <h1>Hello, {this.props.name}</h1>;
         }
       }
    

注意:

  1. 组件名称必须以大写字母开头。
  2. React 会将以小写字母开头的组件视为原生 DOM 标签。例如,<div /> 代表 HTML 的 div 标签,而 <Welcome /> 则代表一个组件,并且需在作用域内使用 Welcome
  3. 你可以在深入 JSX 中了解更多关于此规范的原因。

ant-design UI组件库

ant-design

安装引入: 从 yarn 或 npm 安装并引入 antd。

yarn add antd

修改 src/App.css,在文件顶部引入 antd/dist/antd.css

@import '~antd/dist/antd.css';

修改 src/App.js,引入 antd 的按钮组件。

import React from 'react';
import { Button } from 'antd';
import './App.css';

const App = () => (
  <div className="App">
    <Button type="primary">Button</Button>
  </div>
);

export default App;

好了,现在你应该能看到页面上已经有了 antd 的蓝色按钮组件了。

JSX

注意:

  1. 在 JSX 中给元素添加类, 需要使用 className 代替 class。
  2. label 的 for属性,使用htmlFor代替。
  3. 在 JSX 中通过 {} 中间解析js代码。
  4. 在 JSX 中只能使用表达式,但是不能出现 语句。
  5. 在 JSX 中注释语法:{/* 中间是注释的内容 */}。
  6. JSx中,return,需要使用小括号包裹。
  7. 必须有返回值.return。
  8. 必须要有一个根节点。<div>xxxx</div>

props 和 state

属性:props

组件之间传递数据。类似于Vue中的Props。 注意点: props只读,无法给props添加或修改属性。组件无论是使用函数声明还是通过 class 声明,都绝不能修改自身的 props。

状态:state

状态即数据

  1. 作用:提供模板渲染的数据。如果是和模板渲染无关的数据。

注意:

  1. 只有通过class创建的组件才具有状态
  2. 状态是私有的,完全由组件来控制
  3. 不要在 state 中添加 render() 方法中不需要的数据,会影响渲染性能!
  4. 正确地使用 State

组件通信

  1. 父组件-->子组件: props。
  2. 子组件-->父组件: props中的回调。
  3. 具体详细的组件通信请看这里

产出Demo

List.js

table展示数据。支持删除和编辑。

import React, { Component } from "react";
import { Button, Card, Divider, Table, Space, Popconfirm } from "antd";
import { uniqueId } from "lodash";

import Form from "./form";

export default class List extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isOpen: false,
      dataSource: [
        {
          key: "1",
          name: "胡彦斌",
          age: 32,
          address: "西湖区湖底公园1号",
        },
        {
          key: "2",
          name: "胡彦祖",
          age: 42,
          address: "西湖区湖底公园1号",
        },
      ],
    };
    this.columns = [
      {
        title: "姓名",
        dataIndex: "name",
        key: "name",
      },
      {
        title: "年龄",
        dataIndex: "age",
        key: "age",
      },
      {
        title: "住址",
        dataIndex: "address",
        key: "address",
      },
      {
        title: "操作",
        key: "action",
        render: (_, record, index) => {
          return (
            <Space size="middle">
              <Button type="primary">编辑</Button>
              <Popconfirm
                title="Sure to delete?"
                onConfirm={() => this.handleDelete(record.key, index)}
              >
                <Button type="primary" danger>
                  删除
                </Button>
              </Popconfirm>
            </Space>
          );
        },
      },
    ];
  }

  handleDelete(rowKey, index) {
    console.log(index, "===", this);
    // const dataList = JSON.parse(JSON.stringify(this.state.dataSource));
    // const newList = dataList.splice(index, 1);
    // console.log(newList,dataList)
    // this.setState({dataSource: dataList});

    const newData = this.state.dataSource.filter((item) => item.key !== rowKey);
    this.setState({ dataSource: newData });
  }

  handleAddForm() {
    this.setState({ isOpen: true });
  }

  closeDialog(values) {
    values.key = uniqueId("add_");

    this.setState({
      isOpen: false,
      dataSource: [...this.state.dataSource, values],
    });
  }

  render() {
    return (
      <div>
        <Card hoverable={true}>
          <Button type="primary" onClick={this.handleAddForm.bind(this)}>
            {this.props.btnName}
          </Button>
          {/* this.props.btnName---> 接收App.js传递的参数 */}
        </Card>
        <Divider plain>分割线</Divider>
        <Card hoverable={true}>
          <Table
            bordered
            dataSource={this.state.dataSource}
            columns={this.columns}
          />
        </Card>
        <Form
          isOpen={this.state.isOpen}
          closeDialog={(values) => this.closeDialog(values)}
        ></Form>
      </div>
    );
  }
}

注意:

  1. state和setState。使用 setState() 方法修改状态,状态改变后,React会重新渲染组件。不要直接修改state属性的值,不会重新渲染组件。
  2. 组件绑定事件。 事件名称采用驼峰命名法。通过React事件机制 onClick 绑定。也可以通过ref操作dom绑定事件。戳这里
  3. 事件绑定中的this。通过 bind 绑定和通过 箭头函数 绑定。 image.png

form.js

信息录入。写了函数组件和class组件。

函数组件

import React from "react";
import PropTypes from "prop-types";
import { Button, Modal, Form, Input, InputNumber } from "antd";
const { TextArea } = Input;

const FormData = (props) => {
  const isModalVisible = props.isOpen;
  const onFinish = (values) => {
    props.closeDialog(values);
  }
  const newLocal = (
    <Form
      name="basic"
      labelCol={{ span: 8 }}
      wrapperCol={{ span: 16 }}
      autoComplete="off"
      initialValues={{
        name: "张三",
        age: 12,
        address: "西湖区湖底公园1号",
      }}
      onFinish={(values) => onFinish(values)}
    >
      <Form.Item
        label="姓名"
        name="name"
        rules={[{ required: true, message: "请输入名称" }]}
      >
        <Input />
      </Form.Item>

      <Form.Item
        label="年龄"
        name="age"
        rules={[{ required: true, message: "请输入年龄" }]}
      >
        <InputNumber />
      </Form.Item>

      <Form.Item label="地址" name="address">
        <TextArea rows={4} />
      </Form.Item>

      <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
        <Button type="primary" htmlType="submit">
          创 建
        </Button>
      </Form.Item>
    </Form>
  );

  return (
    <div>
      <Modal title="Basic Modal" visible={isModalVisible} footer={null}>
        {newLocal}
      </Modal>
    </div>
  );
};

FormData.propTypes = {
  
};

export default FormData;

class组件

import React, { Component } from "react";
import { Button, Modal, Checkbox, Form, Input, InputNumber } from "antd";
const { TextArea } = Input;

export default class FormData extends Component {
  constructor(props) {
    super(props);
  }

  onFinish(values) {
    this.props.closeDialog(values);
  }

  render() {
    const isModalVisible = this.props.isOpen;
    const newLocal = <Form
      name="basic"
      labelCol={{ span: 8 }}
      wrapperCol={{ span: 16 }}
      autoComplete="off"
      initialValues={{
        name: "张三",
        age: 12,
        address: "西湖区湖底公园1号",
      }}
      onFinish={(values) => this.onFinish(values)}
    >
      <Form.Item
        label="姓名"
        name="name"
        rules={[{ required: true, message: "请输入名称" }]}
      >
        <Input />
      </Form.Item>

      <Form.Item
        label="年龄"
        name="age"
        rules={[{ required: true, message: "请输入年龄" }]}
      >
        <InputNumber />
      </Form.Item>

      <Form.Item label="地址" name="address">
        <TextArea rows={4} />
      </Form.Item>

      <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
        <Button
          type="primary"
          htmlType="submit"
        >
          创 建
        </Button>
      </Form.Item>
    </Form>;



    return (
      <div>
        <Modal
          title="Basic Modal"
          visible={isModalVisible}
          footer={null}
        >
          {newLocal}
        </Modal>
      </div>
    );
  }
}

image.png

总结

  1. 我们从零开始,构建了React项目,安装了ant-design搭配的UI框架,实现了列表展示、表单录入数据,可删除的功能。
  2. 初步学习了props,state和组件之间的通信。
  3. 这里也收集了比较优秀的文章React入门看这篇就够了;
  4. 推荐两个学习React,在vscode编辑器上比较友好的插件: React Component VSCode React Refactor