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

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

从零开始,搭建一个简单的购物平台(六):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", width: 200 },
      {
        align: "center",
        title: "邮箱",
        dataIndex: "mailaddress",
        width: 200,
        render: (text, data) => {
          return <div>{text + data.mailurl}</div>;
        },
      },
      {
        align: "center",
        title: "密码",
        dataIndex: "password",
        width: 300,
      },
      {
        align: "center",
        title: "头像",
        dataIndex: "headPic",
        width: 150,
        render: (imgPath) => {
          return (
            <img
              src={FilePath + imgPath}
              alt=""
              style={{ width: 60, margin: "0 auto" }}
            />
          );
        },
      },
      {
        align: "center",
        title: "性别",
        dataIndex: "sex",
        width: 200,
        render: (sex) => {
          return <div>{sex == "man" ? "男" : "女"}</div>;
        },
      },
      {
        align: "center",
        title: "收货地址",
        dataIndex: "alladdress",
        width: 200,
        render: (text, data, index) => {
          return <div>{text.join("-") + data.address}</div>;
        },
      },
      {
        align: "center",
        title: "个性签名",
        dataIndex: "descript",
        width: 200,
      },
      {
        align: "center",
        title: "用户类型",
        dataIndex: "userType",
        width: 200,
        render: (type) => {
          return <div>{type == "admin" ? "管理员" : "用户"}</div>;
        },
      },
      {
        align: "center",
        title: "注册时间",
        dataIndex: "time",
        width: 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) => {});
  };
}

全部完成后,测试一下

1.gif


总结


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


相关文章
|
运维 前端开发 NoSQL
从零开始,手把手教你实现一个高效的OA会议系统
从零开始,手把手教你实现一个高效的OA会议系统
167 0
|
前端开发 测试技术 数据库
从零开始,搭建一个简单的购物平台(三)
从零开始,搭建一个简单的购物平台(三)
102 1
从零开始,搭建一个简单的购物平台(三)
|
前端开发 数据管理
从零开始,搭建一个简单的购物平台(五)
从零开始,搭建一个简单的购物平台(五)
318 1
从零开始,搭建一个简单的购物平台(五)
|
前端开发 数据库连接 数据库
从零开始,搭建一个简单的购物平台(二)
从零开始,搭建一个简单的购物平台(二)
187 1
从零开始,搭建一个简单的购物平台(二)
|
前端开发 JavaScript 数据库
从零开始,搭建一个简单的购物平台(十五)前端商城部分
从零开始,搭建一个简单的购物平台(十五)前端商城部分
218 1
从零开始,搭建一个简单的购物平台(十五)前端商城部分
|
前端开发
从零开始,搭建一个简单的购物平台(十六)前端商城部分
从零开始,搭建一个简单的购物平台(十六)前端商城部分
236 1
从零开始,搭建一个简单的购物平台(十六)前端商城部分
|
缓存 前端开发 数据库
从零开始,搭建一个简单的购物平台(四)
从零开始,搭建一个简单的购物平台(四)
135 0
从零开始,搭建一个简单的购物平台(四)
|
前端开发
从零开始,搭建一个简单的购物平台(九)
从零开始,搭建一个简单的购物平台(九)
229 0
从零开始,搭建一个简单的购物平台(九)
|
前端开发 数据库
从零开始,搭建一个简单的购物平台(十)
从零开始,搭建一个简单的购物平台(十)
238 0
从零开始,搭建一个简单的购物平台(十)
|
前端开发 JavaScript NoSQL
从零开始,搭建一个简单的购物平台(一)
从零开始,搭建一个简单的购物平台(一)
447 0
从零开始,搭建一个简单的购物平台(一)