从零开始,搭建一个简单的购物平台(六):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) => {}); }; }
全部完成后,测试一下
总结
在组件化开发的前端代码中,组件复用可以使代码可维护性提升,通过修改state或者初始状态值对相对应的组件进行使用,大大提升代码效率