Start from scratch, build a simple shopping platform (6): https://blog.csdn.net/time_____/article/details/105440818
Project source code (continuous update): https://gitee.com/DieHunter/myCode/ tree/master/shopping
Up to now, the front-end and back-end functions of the project have realized login, token acquisition and verification, upload avatars, and add users. This article mainly describes the realization of front-end and back-end user list page search, fuzzy query, and user list rendering functions.
- The first is paging search. The back-end implementation method uses the length of the database to look up the table, with the database function skip(n) (skip the first n data), and limit(m) (search m data backward), through db.find ().skip((page-1) * pageSize).limit(pageSize) (page represents the number of pages, starting from 0, the first page does not need to be skipped. pageSize represents the number of data items per page after paging), so We create two new methods in command.js for querying the length of the table and keyword query and pagination
/* 查询分页
* @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 };
}
- Add an interface to get the user list in users.js, search by email or username, and paging
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: "查找成功",
});
});
After the back-end part is implemented, start to write the front-end. The form component, the paging component and the input search component are needed. Here, the form component can be written separately and written as our own component for reuse in the later product list.
- First configure the user form fields and encapsulate them in a 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,
},
];
}
}
- Before the table is rendered, determine the type of the table, whether to display the user or the product, to achieve the component reuse function, and bind the paging component to pageconfig to achieve the effect of switching pages
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);
};
}
- Finally, it is called in the userlist to achieve a data two-way binding effect with the page in the table
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) => {});
};
}
- After all is done, test it
to sum up
In the component-based development of front-end code, component reuse can improve the maintainability of the code. By modifying the state or initial state value to use the corresponding component, the code efficiency is greatly improved