1. CRUD-增删改查
- C-Create
- R-Read
- U-Update
- D-Delete
restful接口规范:
可以直接把一个json文件,转化为支持restful接口规范的接口
- 一种通用的接口规范
- 一种地址不同的类型对应不同的操作
C-Create | /user | post 新增用户 请求体参数 body |
---|---|---|
R-Read | /user | get 获取用户列表 /user/:id 获取用户详情 |
U-Update | /user/:id | put(完整更新) patch(增量更新) 请求体参数 { name, age, sex } |
D-Delete | /user/:id | delete |
2. json-server
前端有一个工具,可以直接生成接口:json-server
2.1 直接使用npx就可以启动接口, 可以直接把json转化成服务器
$ npx json-server --watch json地址 --port 端口号
2.2 新建一个json文件
{
"setting": [
{
"id": 1,
"name": "管理员",
"describe": "管理员"
},
{
"id": 2,
"name": "财务专员",
"describe": "财务专员"
},
{
"id": 3,
"name": "薪酬专员",
"describe": "薪酬专员"
}
]
}
2.3 启动接口
$ npx json-server --watch ./abc.json --port 8899
启动之后,就拥有了增删改查的所有接口
3.两种方式完成-CRUD项目
3.1通过class组件完成
- 使用create-react-app创建一个项目-去处严格模式- index.js中 删除React.StrictMode节点
- 启动项目-接入antd组件库
- 访问antd官网 antd官网
- 快速接入
$ yarn add antd
- 在App.js 应用组件即可
import {
Button } from "antd"
import "antd/dist/antd.css"
function App() {
return (
<div className="App">
<Button type="primary">按钮</Button>
</div>
)
}
export default App
- 安装请求工具axios
$ yarn add axios
- 封装请求工具 src/utils/request.js
import axios from "axios"
const service = axios.create({
baseURL: "http://localhost:8899",
}) // 实例化请求工具
service.interceptors.response.use((response) => {
// axios默认包了一层data数据
return response.data
})
export default service
- 封装增删改查5个接口 src/api/setting.js
import request from "../utils/request"
// 获取角色列表
export function getRoleList() {
return request({
url: "/setting",
})
}
// 获取角色详情
export function getRoleDetail(id) {
return request({
url: `/setting/${
id}`,
})
}
// 删除角色详情
export function delRole(id) {
return request({
url: `/setting/${
id}`,
method: "delete",
})
}
// 新增角色
export function addRole(data) {
return request({
url: `/setting`,
method: "post",
// params, // 地址参数 拼在url地址上
data,
})
}
// 修改角色
export function updateRole(data) {
return request({
url: `/setting/${
data.id}`,
method: "patch",
data, // 请求体参数
})
}
- 实现列表的布局-获取数据
import {
Button, Card, Table, Space } from "antd"
import "antd/dist/antd.css"
import {
Component } from "react"
import {
getRoleList } from "./api/setting"
class App extends Component {
state = {
list: [],
}
getColumns() {
return [
{
title: "序号",
dataIndex: "id",
align: "center",
},
{
title: "角色名称",
dataIndex: "name",
key: "name",
align: "center",
},
{
title: "角色描述",
dataIndex: "describe",
key: "describe",
align: "center",
},
{
title: "操作",
key: "operate",
align: "center",
render: () => (
<Space>
<Button type="primary">编辑</Button>
<Button type="primary" danger>
删除
</Button>
</Space>
),
},
]
}
componentDidMount() {
this.getRoleList()
}
async getRoleList() {
const list = await getRoleList()
this.setState({
list,
})
}
render() {
const {
list } = this.state
return (
<Card>
<Button type="primary">新增角色</Button>
<div style={
{
height: 30 }}></div>
<Table
pagination={
false}
dataSource={
list}
bordered
columns={
this.getColumns()}
rowKey="id"
></Table>
</Card>
)
}
}
export default App
- 删除角色- 拿到要删除的id, 提示一下,调用接口- 重新拉取数据
- 注册删除事件
引入弹层插件
import {
Modal, message } from 'antd'
{
title: "操作",
key: "operate",
align: "center",
render: (text, row) => (
<Space>
<Button type="primary">编辑</Button>
<Button type="primary" danger onClick={
() => this.delRole(row.id)}>
删除
</Button>
</Space>
),
},
声明删除方法
delRole(id) {
Modal.confirm({
title: "提示",
content: "您确认要删除此条数据吗",
onOk: async () => {
// 确认要删除了
await delRole(id)
message.success("删除角色成功")
this.getRoleList()
},
})
}
Antd的table表格需要给一个唯一的属性 rowKey=“字段”, 字段的值需要是唯一的。
新增操作-封装一个新增的组件 src/components/AddRole.jsx
import {
Component, createRef } from "react"
import {
Modal, Form, Input, message } from "antd"
import {
addRole } from "../api/setting"
export default class AddRole extends Component {
formRef = createRef()
async onSubmit() {
const {
addSuccess } = this.props
// 完成校验
const res = await this.formRef.current.validateFields()
await addRole(res)
message.success("添加用户成功")
this.formRef.current.resetFields() // 重置字段
addSuccess && addSuccess()
}
onCancel() {
this.formRef.current.resetFields() // 重置字段
this.props.addSuccess && this.props.addSuccess(false) // 传false得意思是 不用重新拉取数据
}
render() {
const {
showDialog } = this.props
return (
<Modal
title="新增角色"
visible={
showDialog}
onOk={
this.onSubmit.bind(this)}
onCancel={
this.onCancel.bind(this)}
>
<Form ref={
this.formRef}>
<Form.Item
name="name"
label="角色名称"
rules={
[
{
required: true,
message: "角色名称不能为空",
},
]}
>
<Input></Input>
</Form.Item>
<Form.Item
name="describe"
label="角色描述"
rules={
[
{
required: true,
message: "角色描述不能为空",
},
]}
>
<Input></Input>
</Form.Item>
</Form>
</Modal>
)
}
}
App.js
import {
Button, Card, Table, Space, Modal, message } from "antd"
import "antd/dist/antd.css"
import {
Component } from "react"
import {
getRoleList, delRole } from "./api/setting"
import AddRole from "./components/AddRole"
class App extends Component {
state = {
list: [],
showDialog: false,
}
getColumns() {
return [
{
title: "序号",
dataIndex: "id",
align: "center",
},
{
title: "角色名称",
dataIndex: "name",
key: "name",
align: "center",
},
{
title: "角色描述",
dataIndex: "describe",
key: "describe",
align: "center",
},
{
title: "操作",
key: "operate",
align: "center",
render: (text, row) => (
<Space>
<Button type="primary">编辑</Button>
<Button type="primary" danger onClick={
() => this.delRole(row.id)}>
删除
</Button>
</Space>
),
},
]
}
componentDidMount() {
this.getRoleList()
}
delRole(id) {
Modal.confirm({
title: "提示",
content: "您确认要删除此条数据吗",
onOk: async () => {
// 确认要删除了
await delRole(id)
message.success("删除角色成功")
this.getRoleList()
},
})
}
async getRoleList() {
const list = await getRoleList()
this.setState({
list,
})
}
addSuccess(reload = true) {
this.setState({
showDialog: false,
})
reload && this.getRoleList()
}
render() {
const {
list, showDialog } = this.state
return (
<Card>
<Button
type="primary"
onClick={
() => this.setState({
showDialog: true })}
>
新增角色
</Button>
<div style={
{
height: 30 }}></div>
<Table
pagination={
false}
dataSource={
list}
bordered
columns={
this.getColumns()}
rowKey="id"
></Table>
<AddRole
showDialog={
showDialog}
addSuccess={
this.addSuccess.bind(this)}
></AddRole>
</Card>
)
}
}
export default App
编辑功能实现
AddRole.jsx
import {
Component, createRef } from "react"
import {
Modal, Form, Input, message } from "antd"
import {
addRole, getRoleDetail, updateRole } from "../api/setting"
export default class AddRole extends Component {
formRef = createRef()
async onSubmit() {
const {
addSuccess } = this.props
// 完成校验
const res = await this.formRef.current.validateFields()
if (res.id) {
// 编辑
await updateRole(res)
message.success("编辑用户成功")
} else {
await addRole(res)
message.success("添加用户成功")
}
this.formRef.current.resetFields() // 重置字段
addSuccess && addSuccess()
}
onCancel() {
this.formRef.current.resetFields() // 重置字段
this.props.addSuccess && this.props.addSuccess(false) // 传false得意思是 不用重新拉取数据
}
// 获取角色的详情的方法
async getRoleDetail(id) {
this.formRef.current.setFieldsValue(await getRoleDetail(id)) // 不会造成render
this.forceUpdate()
// this.setState forceUpdate()
}
render() {
const {
showDialog } = this.props
return (
<Modal
title={
this.formRef.current?.getFieldValue("id") ? "编辑角色" : "新增角色"
}
visible={
showDialog}
onOk={
this.onSubmit.bind(this)}
onCancel={
this.onCancel.bind(this)}
>
<Form ref={
this.formRef}>
<Form.Item name="id" style={
{
display: "none" }}>
<Input></Input>
</Form.Item>
<Form.Item
name="name"
label="角色名称"
rules={
[
{
required: true,
message: "角色名称不能为空",
},
]}
>
<Input></Input>
</Form.Item>
<Form.Item
name="describe"
label="角色描述"
rules={
[
{
required: true,
message: "角色描述不能为空",
},
]}
>
<Input></Input>
</Form.Item>
</Form>
</Modal>
)
}
}
App.js
import {
Button, Card, Table, Space, Modal, message } from "antd"
import "antd/dist/antd.css"
import {
Component, createRef } from "react"
import {
getRoleList, delRole } from "./api/setting"
import AddRole from "./components/AddRole"
class App extends Component {
state = {
list: [],
showDialog: false,
}
childRef = createRef()
getColumns() {
return [
{
title: "序号",
dataIndex: "id",
align: "center",
},
{
title: "角色名称",
dataIndex: "name",
key: "name",
align: "center",
},
{
title: "角色描述",
dataIndex: "describe",
key: "describe",
align: "center",
},
{
title: "操作",
key: "operate",
align: "center",
render: (text, row) => (
<Space>
<Button type="primary" onClick={
() => this.editRole(row.id)}>
编辑
</Button>
<Button type="primary" danger onClick={
() => this.delRole(row.id)}>
删除
</Button>
</Space>
),
},
]
}
componentDidMount() {
this.getRoleList()
}
delRole(id) {
Modal.confirm({
title: "提示",
content: "您确认要删除此条数据吗",
onOk: async () => {
// 确认要删除了
await delRole(id)
message.success("删除角色成功")
this.getRoleList()
},
})
}
// 编辑角色
editRole(id) {
this.setState(
{
showDialog: true,
},
() => {
// 这里获取子组件的ref对象
// 拿到ref对象 拿到子组件的this 调用组件的方法
this.childRef.current.getRoleDetail(id)
}
)
}
async getRoleList() {
const list = await getRoleList()
this.setState({
list,
})
}
addSuccess(reload = true) {
this.setState({
showDialog: false,
})
reload && this.getRoleList()
}
render() {
const {
list, showDialog } = this.state
return (
<Card>
<Button
type="primary"
onClick={
() => this.setState({
showDialog: true })}
>
新增角色
</Button>
<div style={
{
height: 30 }}></div>
<Table
pagination={
false}
dataSource={
list}
bordered
columns={
this.getColumns()}
rowKey="id"
></Table>
<AddRole
ref={
this.childRef}
showDialog={
showDialog}
addSuccess={
this.addSuccess.bind(this)}
></AddRole>
</Card>
)
}
}
export default App
3.2通过函数组件 + hooks 完成CRUD
使用antd组件库
1.create-react-app创建项目
$ npx create-react-app setting-hooks
2.安装antd组件库
$ yarn add antd
3.在index.js中引入Antd的样式
import "antd/dist/antd.css"
4.构建布局
构建布局之前,要有接口- 使用json-server启动接口
$ npx json-server --watch ./abc.json --port 8899
5.安装axios
$ yarn add axios
6.封装请求工具-src/utils/request.js
import axios from "axios"
const service = axios.create({
baseURL: "http://localhost:8899",
})
service.interceptors.response.use((response) => {
return response.data // axios默认包了一层data
})
export default service
7.封装单独的api- src/api/setting.js
import request from "../utils/request"
// restful接口规范
export function getRoleList() {
return request({
url: "/setting",
})
}
export function getRoleDetail(id) {
return request({
url: `/setting/${
id}`,
})
}
export function delRole(id) {
return request({
url: `/setting/${
id}`,
method: "delete",
})
}
export function updateRole(data) {
return request({
url: `/setting/${
data.id}`,
method: "patch",
data,
})
}
export function addRole(data) {
return request({
url: `/setting`,
method: "post",
data,
})
}
8.搭建页面布局 Card-Button-Table
import {
Button, Card, Table } from "antd"
function App() {
const columns = [
{
title: "序号",
dataIndex: "id",
align: "center",
},
{
title: "角色名称",
dataIndex: "name",
align: "center",
},
{
title: "角色描述",
dataIndex: "describe",
align: "center",
},
{
title: "操作",
align: "center",
},
]
return (
<Card>
<Button type="primary">新增角色</Button>
<div style={
{
height: 40 }}></div>
<Table columns={
columns} bordered></Table>
</Card>
)
}
export default App
9.获取角色列表数据
import {
Button, Card, Table } from "antd"
import {
useState, useEffect } from "react"
import {
getRoleList } from "./api/setting"
function App() {
const [list, setList] = useState([])
useEffect(() => {
getList()
}, [])
const getList = async () => {
setList(await getRoleList())
}
const columns = [
{
title: "序号",
dataIndex: "id",
align: "center",
},
{
title: "角色名称",
dataIndex: "name",
align: "center",
},
{
title: "角色描述",
dataIndex: "describe",
align: "center",
},
{
title: "操作",
align: "center",
},
]
return (
<Card>
<Button type="primary">新增角色</Button>
<div style={
{
height: 40 }}></div>
<Table
pagination={
false}
rowKey="id"
columns={
columns}
bordered
dataSource={
list}
></Table>
</Card>
)
}
export default App
10.删除动作
import {
Button, Card, Space, Table, Modal, message } from "antd"
import {
useState, useEffect } from "react"
import {
getRoleList, delRole } from "./api/setting"
function App() {
const [list, setList] = useState([])
useEffect(() => {
getList()
}, [])
const getList = async () => {
setList(await getRoleList())
}
const delRoleHandle = (id) => {
// 提示确认
Modal.confirm({
title: "提示",
content: "确认要删除该角色吗",
async onOk() {
await delRole(id)
message.success("删除角色成功")
getList()
},
})
}
const columns = [
{
title: "序号",
dataIndex: "id",
align: "center",
},
{
title: "角色名称",
dataIndex: "name",
align: "center",
},
{
title: "角色描述",
dataIndex: "describe",
align: "center",
},
{
title: "操作",
align: "center",
render(text, record, index) {
return (
<Space>
<Button type="primary">编辑</Button>
<Button
type="primary"
onClick={
() => delRoleHandle(record.id)}
danger
>
删除
</Button>
</Space>
)
},
},
]
return (
<Card>
<Button type="primary">新增角色</Button>
<div style={
{
height: 40 }}></div>
<Table
pagination={
false}
rowKey="id"
columns={
columns}
bordered
dataSource={
list}
></Table>
</Card>
)
}
export default App
11.新增操作- component/AddRole.jsx
import {
Modal, Form, Input } from "antd"
const AddRole = () => {
return (
<Modal title="新增角色" visible={
true}>
<Form>
<Form.Item label="角色名称">
<Input></Input>
</Form.Item>
<Form.Item label="角色描述">
<Input></Input>
</Form.Item>
</Form>
</Modal>
)
}
export default AddRole
12.新增功能的实现
import {
Modal, Form, Input, message } from "antd"
import {
addRole } from "../api/setting"
const AddRole = ({
showDialog, addSuccess }) => {
const [form] = Form.useForm()
const onSubmit = async () => {
// 做校验- 提交、
const result = await form.validateFields()
await addRole(result)
form.resetFields() // 重置字段
message.success("新增角色成功")
addSuccess && addSuccess()
}
return (
<Modal onOk={
onSubmit} title="新增角色" visible={
showDialog}>
<Form form={
form}>
<Form.Item
rules={
[{
required: true, message: "角色名称不能为空" }]}
name="name"
label="角色名称"
>
<Input></Input>
</Form.Item>
<Form.Item
rules={
[{
required: true, message: "角色描述不能为空" }]}
name="describe"
label="角色描述"
>
<Input></Input>
</Form.Item>
</Form>
</Modal>
)
}
export default AddRole
App.js
import {
Button, Card, Space, Table, Modal, message } from "antd"
import {
useState, useEffect } from "react"
import {
getRoleList, delRole } from "./api/setting"
import AddRole from "./components/AddRole"
function App() {
const [list, setList] = useState([])
const [showDialog, setShowDialog] = useState(false)
useEffect(() => {
getList()
}, [])
const getList = async () => {
setList(await getRoleList())
}
const delRoleHandle = (id) => {
// 提示确认
Modal.confirm({
title: "提示",
content: "确认要删除该角色吗",
async onOk() {
await delRole(id)
message.success("删除角色成功")
getList()
},
})
}
// 子组件告诉父组件-新增成功
const addSuccess = () => {
setShowDialog(false) // 关闭弹层
getList()
}
const columns = [
{
title: "序号",
dataIndex: "id",
align: "center",
},
{
title: "角色名称",
dataIndex: "name",
align: "center",
},
{
title: "角色描述",
dataIndex: "describe",
align: "center",
},
{
title: "操作",
align: "center",
render(text, record, index) {
return (
<Space>
<Button type="primary">编辑</Button>
<Button
type="primary"
onClick={
() => delRoleHandle(record.id)}
danger
>
删除
</Button>
</Space>
)
},
},
]
return (
<Card>
<Button type="primary" onClick={
() => setShowDialog(true)}>
新增角色
</Button>
<div style={
{
height: 40 }}></div>
<Table
pagination={
false}
rowKey="id"
columns={
columns}
bordered
dataSource={
list}
></Table>
<AddRole showDialog={
showDialog} addSuccess={
addSuccess}></AddRole>
</Card>
)
}
export default App
13.编辑功能的是实现
AddRole.jsx
import {
Modal, Form, Input, message } from "antd"
import {
addRole, getRoleDetail, updateRole } from "../api/setting"
import {
useEffect, useMemo } from "react"
const AddRole = ({
showDialog, addSuccess, currentId }) => {
const [form] = Form.useForm()
const onSubmit = async () => {
// 做校验- 提交、
const result = await form.validateFields()
if (result.id) {
await updateRole(result)
message.success("编辑角色成功")
} else {
await addRole(result)
message.success("新增角色成功")
}
form.resetFields() // 重置字段
addSuccess && addSuccess()
}
const onCancel = () => {
form.resetFields() // 重置字段
addSuccess && addSuccess(false)
}
useEffect(() => {
// 第一次执行 + currentId发生变化
if (currentId) {
// 只有不为空的情况下 才获取详情数据
const getDetail = async () => {
form.setFieldsValue(await getRoleDetail(currentId))
}
getDetail()
}
}, [currentId, form])
// form不会发生变化- 固定对象-这里放入form只会遵循 不要对依赖项撒谎的规范
// useMemo类似Vue计算属性- 返回的结果 只会在依赖项发生变化时重新计算
const title = useMemo(() => {
return currentId ? "编辑角色" : "新增角色"
}, [currentId])
return (
<Modal
onCancel={
onCancel}
onOk={
onSubmit}
title={
title}
visible={
showDialog}
>
<Form form={
form}>
<Form.Item name="id" style={
{
display: "none" }}>
<Input></Input>
</Form.Item>
<Form.Item
rules={
[{
required: true, message: "角色名称不能为空" }]}
name="name"
label="角色名称"
>
<Input></Input>
</Form.Item>
<Form.Item
rules={
[{
required: true, message: "角色描述不能为空" }]}
name="describe"
label="角色描述"
>
<Input></Input>
</Form.Item>
</Form>
</Modal>
)
}
export default AddRole
App.js
import {
Button, Card, Space, Table, Modal, message } from "antd"
import {
useState, useEffect } from "react"
import {
getRoleList, delRole } from "./api/setting"
import AddRole from "./components/AddRole"
function App() {
const [list, setList] = useState([])
const [showDialog, setShowDialog] = useState(false)
const [currentId, setCurrentId] = useState(null)
useEffect(() => {
getList()
}, [])
const getList = async () => {
setList(await getRoleList())
}
const delRoleHandle = (id) => {
// 提示确认
Modal.confirm({
title: "提示",
content: "确认要删除该角色吗",
async onOk() {
await delRole(id)
message.success("删除角色成功")
getList()
},
})
}
// 编辑角色
const editRole = (id) => {
// id 是用来获取角色详情
setCurrentId(id) // 设置当前编辑的行的数据的ID
setShowDialog(true) // 打开弹层
}
// 子组件告诉父组件-新增成功
const addSuccess = (reload = true) => {
setCurrentId(null) // 重置id
setShowDialog(false) // 关闭弹层
reload && getList()
}
const columns = [
{
title: "序号",
dataIndex: "id",
align: "center",
},
{
title: "角色名称",
dataIndex: "name",
align: "center",
},
{
title: "角色描述",
dataIndex: "describe",
align: "center",
},
{
title: "操作",
align: "center",
render(text, record, index) {
return (
<Space>
<Button type="primary" onClick={
() => editRole(record.id)}>
编辑
</Button>
<Button
type="primary"
onClick={
() => delRoleHandle(record.id)}
danger
>
删除
</Button>
</Space>
)
},
},
]
return (
<Card>
<Button type="primary" onClick={
() => setShowDialog(true)}>
新增角色
</Button>
<div style={
{
height: 40 }}></div>
<Table
pagination={
false}
rowKey="id"
columns={
columns}
bordered
dataSource={
list}
></Table>
<AddRole
currentId={
currentId}
showDialog={
showDialog}
addSuccess={
addSuccess}
></AddRole>
</Card>
)
}
export default App