• 从零开始,搭建一个简单的购物平台(七)


    从零开始,搭建一个简单的购物平台(六):https://blog.csdn.net/time_____/article/details/105440818
    项目源码(持续更新):https://gitee.com/DieHunter/myCode/tree/master/shopping

    到现在为止,项目前后端功能已实现登录,token获取验证,上传头像,添加用户,这篇文章主要讲述实现前后端用户列表分页查找,模糊查询,用户列表渲染功能

    • 首先是分页查找,后端实现方式通过数据库查找表的长度,配合数据库函数skip(n)(跳过前n条数据),和limit(m)(向后查找m条数据),通过db.find().skip((page - 1) * pageSize).limit(pageSize)(page代表第几页,从0开始,第一页则不需要跳过。pageSize表示分页后每页数据条数),所以我们在command.js中新建两个方法,用于查询表的长度和关键字查询并分页
     /* 查询分页
       * @param {object} mod       数据库model
       * @param {number} sort      排序顺序   负数倒序 正数顺序
       * @param {number} page      当前页数
       * @param {number} pageSize  分页大小
       * @param {object} pageSize  关键字模糊查询
       */
      static async findByPage(mod, sort, page, pageSize, keyWord) {
        //分页查
        return await mod
          .find(keyWord)
          .sort(sort)
          .skip((page - 1) * pageSize)
          .limit(pageSize);
      }
     /* 查询分页
       * @param {object} mod       数据库model
       * @param {number} pageSize  分页大小
       */
     static async getTotalPage(mod, pageSize) {
        let allNum = await mod.find().estimatedDocumentCount();
        return { totalPage: parseInt(allNum / pageSize) + 1, allNum };
      }
    • 在users.js中添加获取用户列表的接口,通过电子邮件或者用户名查找,分页
    router.get(Config.ServerApi.userList, Util.checkToken, async (req, res) => {
      if (res._data.userTokenType != "admin") {
        //非管理员
        res.send({
          result: -999,
          msg: "请用管理员账号登录",
        });
        return;
      }
      let total = await getTotalPage(Mod, res._data.pageSize);
      let query = new RegExp(res._data.keyWord, "i"); //模糊查找正则条件
      res.send({
        result: 1,
        data: {
          page: res._data.page,
          pageSize: res._data.pageSize,
          totalPage: total.totalPage,
          allNum: total.allNum,
          list: await findByPage(
            Mod,
            {
              time: res._data.sort,
            },
            res._data.page,
            res._data.pageSize,
            res._data.keyWord.length
              ? {
                  $or: [
                    {
                      mailaddress: query,
                    },
                    {
                      username: query,
                    },
                  ],
                }
              : {}
          ),
        },
        msg: "查找成功",
      });
    });

    后端部分实现完成后,开始编写前端,需要用到表格组件,分页组件和input查找组件,这里可以将表格组件单独写出来,写成我们自己的组件,以供后期商品列表重复使用

    • 先配置一下用户表格字段,封装到一个class里
    import React from "react";
    import {
      Button,
      Popconfirm,
    } from "antd";
    import config from "../../config/config";
    
    const { FilePath } = config;
    export default class UserTable {
      constructor(_this) {
        return [
          { align: "center", title: "用户名", dataIndex: "username",  200 },
          {
            align: "center",
            title: "邮箱",
            dataIndex: "mailaddress",
             200,
            render: (text, data) => {
              return <div>{text + data.mailurl}</div>;
            },
          },
          {
            align: "center",
            title: "密码",
            dataIndex: "password",
             300,
          },
          {
            align: "center",
            title: "头像",
            dataIndex: "headPic",
             150,
            render: (imgPath) => {
              return (
                <img
                  src={FilePath + imgPath}
                  alt=""
                  style={{  60, margin: "0 auto" }}
                />
              );
            },
          },
          {
            align: "center",
            title: "性别",
            dataIndex: "sex",
             200,
            render: (sex) => {
              return <div>{sex == "man" ? "男" : "女"}</div>;
            },
          },
          {
            align: "center",
            title: "收货地址",
            dataIndex: "alladdress",
             200,
            render: (text, data, index) => {
              return <div>{text.join("-") + data.address}</div>;
            },
          },
          {
            align: "center",
            title: "个性签名",
            dataIndex: "descript",
             200,
          },
          {
            align: "center",
            title: "用户类型",
            dataIndex: "userType",
             200,
            render: (type) => {
              return <div>{type == "admin" ? "管理员" : "用户"}</div>;
            },
          },
          {
            align: "center",
            title: "注册时间",
            dataIndex: "time",
             200,
          },
        ];
      }
    }
    
    • 在表格渲染前判断一下表格类型,是显示用户还是商品,达到组件复用功能,将分页组件与pageconfig绑定,达到切换页面的效果
    import React from "react";
    import {
      Table,
      Button,
      Card,
      Pagination,
      Input,
      Col,
      Row,
    } from "antd";
    import userTab from "./userTab";
    import { PlusOutlined } from "@ant-design/icons";
    const { Search } = Input;
    export default class ListTable extends React.Component {
      state = {
        tableType: this.props.tableType,
        pageConfig: {
          totalPage: 0,
          page: 0,
          pageSize: 0,
          allNum: 0,
        },
        columns: [],
        list: [],
      };
      componentDidMount() {
        if (this.state.tableType == "user") {
          this.setState({
            columns: new userTab(this)
          });
        } else {
          
        }
        this.props.onTableRef(this);
      }
      render() {
        return (
          <Card title="用户列表">
            <Row gutter={16}>
              <Col span={12}>
                <Button onClick={this.props.showDrawer} type="primary">
                  <PlusOutlined />
                  新增用户
                </Button>
              </Col>
              <Col span={12}>
                <Search
                  style={{ float: "right" }}
                  placeholder="输入用户名/邮箱"
                  enterButton="查找"
                  size="large"
                  allowClear
                  onSearch={(val) => {
                    let { pageConfig } = this.state;
                    pageConfig.keyWord = val;
                    this.setState({
                      pageConfig,
                    });
                    this.props.changePage(pageConfig);
                  }}
                />
              </Col>
            </Row>
            <Table
              scroll={{ x: 2000 }}
              rowKey={(record) => record._id}
              columns={this.state.columns}
              dataSource={this.state.list}
              pagination={false}
            ></Table>
            <Pagination
              style={{ marginTop: 50 }}
              hideOnSinglePage
              total={this.state.pageConfig.allNum}
              current={this.state.pageConfig.page}
              pageSize={this.state.pageConfig.pageSize}
              showSizeChanger
              showQuickJumper
              showTotal={(total) => `共 ${total} 条`}
              onChange={this.changePage}
              onShowSizeChange={this.changePage}
            />
          </Card>
        );
      }
      changePage = (page, pageSize) => {
        let pageConfig = this.state.pageConfig;
        pageConfig.page = page;
        pageConfig.pageSize = pageSize;
        this.setState({
          pageConfig,
        });
        this.props.changePage(pageConfig);
      };
    }
    
    • 最后在userlist中调用,与表格中的page达到一个数据双向绑定效果
    import React from "react";
    import ListTable from "../../../components/table/table";
    import {
      message,
    } from "antd";
    import config from "../../../config/config";
    const { ServerApi, StorageName } = config;
    
    export default class UserList extends React.Component {
      state = {
        userType: "adduser",
        pageConfig: {
          token: this.$utils.getStorage(StorageName.token),
          keyWord: "",
          page: 1,
          pageSize: 2,
          totalPage: 1,
          sort: 1,
        },
      };
      componentDidMount() {
        this.getUserList();
      }
      render() {
        return (
          <div>
            <ListTable
              tableType="user"
              onTableRef={(child) => {
                this.tableChild = child;
              }}
              showDrawer={this.showDrawer}
              changePage={this.changePage}
            ></ListTable>
            <ListDrower
              getUserList={this.getUserList}
              userType={this.state.userType}
              onDrowerRef={(child) => {
                this.drawerChild = child;
              }}
            ></ListDrower>
          </div>
        );
      }
      showDrawer = () => {
        this.drawerChild.showDrawer();
      };
      changePage = (pageConfig) => {
        this.setState({ pageConfig });
        this.getUserList();
      };
    
      getUserList = () => {
        let data = { ...this.state.pageConfig };
        this.$axios
          .get(ServerApi.user.userList, {
            params: { crypto: this.$crypto.setCrypto(data) },
          })
          .then((res) => {
            let { list, totalPage, allNum } = res.data;
            let { pageConfig } = this.state;
            pageConfig.allNum = allNum;
            pageConfig.totalPage = totalPage;
            this.tableChild.setState({ pageConfig, list });
          })
          .catch((err) => {});
      };
    }
    
    • 全部完成后,测试一下

    总结

    在组件化开发的前端代码中,组件复用可以使代码可维护性提升,通过修改state或者初始状态值对相对应的组件进行使用,大大提升代码效率

  • 相关阅读:
    GDI+学习笔记2
    GDI+学习笔记1- 概述
    Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制
    Java网络编程和NIO详解开篇:Java网络编程基础
    我在阿里工作的这段时间里,都学到了哪些东西
    在大公司做凤尾,还是在小公司做鸡头?
    蚂蚁金服财富技术部,诚招Java研发工程师。校招内推!!!
    测试课程
    新笔记
    阅读书籍电技术
  • 原文地址:https://www.cnblogs.com/HelloWorld-Yu/p/13514435.html
Copyright © 2020-2023  润新知