react项目笔记
# 1. 项目安装运行
# 1-1. 项目clone
git clone https://gitee.com/yuonly0528/react-project.git
# 1-2. 目录结构
06_React_project
|- syt-admin_docs 项目开发文档
|- syt-admin-final 完成的项目
|- syt-admin-react-base 二次开发的项目
2
3
4
# 1-3. final项目安装依赖并运行
修改镜像源:
# 腾讯 npm config set registry http://mirrors.cloud.tencent.com/npm # 淘宝 npm config set registry https://registry.npmmirror.com # npm 原镜像 npm config set registry https://registry.npmjs.org1
2
3
4
5
6启动final项目:进入项目根目录,打开终端
cd syt-admin-final npm i -f # -f force 强制安装 npm start 启动项目1
2
3启动 base项目:进入base项目目录,打开终端
cd syt-admin-react-base npm i -f npm start1
2
3可能出现的错误及解决方案:
- 由于网络原因,导致包没下全。
- 删除node_modules : 切换源 重新 npm i -f安装
- 叉掉错误:对付用
- token异常:
- 删除本地存储的token,刷新页面重新登录
# 2. 接口地址
- 医院接口地址:http://139.198.34.216:8201/swagger-ui.html#/
- 数据字典接口地址:http://139.198.34.216:8202/swagger-ui.html#/259682545423383208563164929702
- 登录接口地址:http://139.198.34.216:8212/swagger-ui.html
# 3. 项目目录文件介绍
├── public # 公共静态资源目录
│ ├── favicon.ico # 网站图标
│ ├── index.html # 主页面
├── src # 主目录
│ ├── api # 接口文件
│ ├── app # redux配置文件
│ ├── components # 公共组件
│ │ ├── Loading # loading组件
│ │ ├── Translation # 国际化组件
│ │ └── withAuthorization # 登陆权限校验组件
│ ├── layouts # 主要布局组件
│ ├── locales # i18n国际化配置
│ ├── pages # 路由组件
│ ├── routes # 路由配置
│ ├── styles # 全局/公共样式
│ ├── utils # 工具函数
│ │ └── http # 封装请求函数
│ ├── App.tsx # App组件
│ ├── index.ts # 主入口
│ ├── react-app-env.d.ts # 类型文件,在编译时会引入额外文件
├── .env.development # 开发环境加载的环境变量配置
├── .env.production # 生产环境加载的环境变量配置
├── .gitignore # git忽略文件
├── craco.config.js # react脚手架配置文件
├── package.json # 包文件
├── README.md # 项目说明文件
├── tsconfig.extend.json # 路径别名配置文件
├── tsconfig.json # ts配置文件
└── yarn.lock # yarn下载包的缓存文件
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 4. 实现功能的流程
- 创建路由组件
- 配置路由
- 创建组件的静态结构
- 查看接口
- 封装 interface
- 封装 api 函数
- 调用 api 函数
- 事件回调
- 钩子函数
- 声明状态
# 5. 医院设置功能实现
# 5-1. 创建路由组件
- 文件创建路径:src/pages/hospital/hospitalSet/HospitalSet.tsx
import React from 'react'
export default function HospitalSet() {
return (
<div>HospitalSet</div>
)
}
2
3
4
5
6
# 5-2. 完成路由配置
- 导入医院设置路由组件 [懒加载方式导入]
- src/routes/index.ts 进行路由配置
- src/routes/index.ts
{
path: "/syt",
element: <Layout />,
children: [
{
// 路由路径
path: "/syt/dashboard",
meta: {
icon: <HomeOutlined />,
title: '首页'
},
element: load(Dashboard),
},
{
path:'/syt/hospital',
meta:{
title:'医院管理',
icon:<ShopOutlined />
},
children:[
{
path:'/syt/hospital/hospitalSet',
meta:{
title:'医院设置'
},
element:load(HospitalSet)
}
]
}
],
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 5-3. 医院设置静态布局完成
import { Button, Card, Form, Input, Space, Table } from 'antd'
import { ColumnsType } from 'antd/lib/table'
import React from 'react'
export default function HospitalSet() {
const columns:ColumnsType<any> = [
{
title:'序号'
},
{
title:'医院名称'
},
{
title:'医院编号'
},
{
title:'api基础路径'
},
{
title:'签名'
},
{
title:'联系人姓名'
},
{
title:'联系人手机'
},
{
title:'操作'
}
]
return (
<Card>
{/* 1. Form */}
<Form
layout='inline'
>
<Form.Item>
<Input placeholder='医院名称' />
</Form.Item>
<Form.Item>
<Input placeholder='医院编号' />
</Form.Item>
<Form.Item>
<Space>
<Button type='primary'>查询</Button>
<Button>清空</Button>
</Space>
</Form.Item>
</Form>
{/* 2. button */}
<Space className='mt'>
<Button type='primary'>添加</Button>
<Button disabled>批量删除</Button>
</Space>
{/* 3. Table */}
<Table
className='mt'
columns={columns}
/>
</Card>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 5-4. 查看接口定义类型-api函数
查看接口:【请求方式、url、参数、返回值】
封装interface: 返回值
封装api函数:
1. path: request.请求方式<any,响应值类型>(url/参数1/参数2...) 2. query: request.请求方式<any,响应值类型>(url, {params:参数key:参数值})1
2
# 5-5. 调用api
- 事件回调
- 钩子函数
# 5-6. 渲染数据
- 定义状态
- 设置状态
# 6. 点击查询获取分页数据
描述: 做了什么,产生了什么结果?
文本框输入内容,点击查询,重新获取分页数据!
拆分步骤:
- 获取文本框输入内容
- 参数:values
- form对象:
- const [form] = Form.useForm()
- 绑定form对象
- form.getFieldsValue获取
- Form.Item 要有name属性 hosname hoscode
- 给查询按钮绑定单击事件
- button htmlType='submit'
- Form onFinish ==> search 函数
- 根据文本框内容发送ajax请求
- 在useEffect 的监听中 监听 hosname hoscode
- 在 onFinish的事件回调中,重新设置 hosname 和 hoscode的状态
# 7. 添加医院
# 7-1. 查看接口
- 请求方式、url、参数、响应结果
- 封装 interface
- 封装api函数
# 7-2. 点击保存
描述:点击保存,将表单中的数据添加到医院列表
步骤:
绑定事件
- 给Form绑定 onFinish 事件
- Button组件 添加 htmlType='submit'
获取表单数据
通过form获取
Form.Item 组件需要有 name属性,并赋值
创建form: const [form] = Form.useForm()
给Form组件绑定form属性
通过form.getFieldsValue获取表单数据
发送ajax请求
调用api函数,发送请求
# 8. 删除医院设置
# 8-1. 查看接口
# 8-2. 实现删除功能
描述:点击删除按钮,根据id删除当前记录
步骤:
- 给删除按钮绑定单击事件,事件回调中要传递当前记录的id
- 根据id,调用api函数,实现删除操作。
- 刷新列表
点击删除按钮弹出 confirm模态框
导入:
- import {Modal} from 'antd'
- 解构:const {confirm} = Modal
调用:
confirm({ title: '确定删除么?', icon: <ExclamationCircleFilled />, content: '删除当前记录', async onOk() { await deleteHospitalSetById(id) message.success('删除成功'); // 刷新列表 _getHospitalSetList(); }, onCancel() { console.log('Cancel'); }, });1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 9. 批量删除
table 配置 rowSelection
rowSelection={{ /** * onChange调用时机,列表复选框发生变化的时候 * @param selectedKeys 选中条id组成的数组 */ onChange(selectedKeys: React.Key[]) { console.log('selectedKeys: ', selectedKeys) setSelectedKeys(selectedKeys); } }}1
2
3
4
5
6
7
8
9
10
- 点击批量删除按钮
<Button disabled={selectedKeys.length === 0} onClick={() => { confirm({ title: '确定批量删除么?', icon: <ExclamationCircleFilled />, content: '批量删除记录', async onOk() { await removeBatch(selectedKeys); // 将selectedKeys状态清空成空数组 setSelectedKeys([]); message.success('批量删除成功'); // 刷新列表 _getHospitalSetList(); }, onCancel() { console.log('Cancel'); }, }); }}>批量删除</Button>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 10. 编辑医院设置
编辑医院设置总共分两个大的步骤:
- 点击编辑按钮,跳转到编辑页面,并获取当前条医院设置数据渲染到表单中
- 点击表单的保存按钮,将用户最新修改的医院设置数据修改原数据
此处,我们将新增医院设置和编辑医院设置共用了同一个页面 AddOrUpdate.tsx ,通过路由参数id,来区分是编辑还是新增操作
# 11. 医院省市区列表
查看接口
封装interface
/** * 省市区 返回数据 对象类型 */ export interface IDistrictItem { id: number; createTime: string; updateTime: string; name: string; value: string; hasChildren: boolean; } /** * 省市区列表类型,也是获取省市区列表接口的返回值类型 */ export type IDistrictList = IDistrictItem[]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15封装api函数
export const getDistrictList = (id: number) => { return request.get<any, IDistrictList>('/admin/cmn/dict/findByParentId/' + id) }1
2
3调用api函数
获取省列表在组件挂载完成后的声明周期钩子调用
市列表是在 省选中后根据 省 id 发请求获取
区列表时在 市选中后根据 市id 发请求获取
- 省列表获取
// 获取省列表 const getProvinceList = async () => { const provinceList = await getDistrictList(86); // 设置省状态数据 setProvinceList(provinceList); } useEffect(() => { getProvinceList(); }, [])1
2
3
4
5
6
7
8
9
- 获取市列表
// 根据省id 获取是列表并渲染 const getCityList = async (id: number) => { console.log('id: ', id); const cityList = await getDistrictList(id); setCityList(cityList); }1
2
3
4
5
6
- 获取区列表
// 根据市id 获取区列表并渲染 const getDictList = async (id: number) => { console.log('city id: ', id); const dictList = await getDistrictList(id); setDictList(dictList); }1
2
3
4
5
6
# 11-1. 省市区联动bug解决
问题描述:当切换省时,应该将原来省的市、区表单的显示恢复成未选择状态,并且将区列表的状态设置为空数组。
设置表单值,需要使用 form对象更方便。
使用form对象的四个步骤:
给Form.Item 设置name属性
创建form: const [form] = Form.useForm()
绑定form
使用form的api操作form
form.getFieldsValue() // 获取表单数据的全部的值 form.setFieldsValue({key1:value1,key2:value2}) // 设置表单数据的值1
2解决联动bug
切换省列表,清空市、区的表单、重置区的状态为空数组
const getCityList = async (id: number) => { console.log('id: ', id); // 将市、区的表单项赋值为undefined form.setFieldsValue({ cityCode:undefined, districtCode:undefined }) // 将区的状态数据设置为空数组 setDictList([]); const cityList = await getDistrictList(id); setCityList(cityList); }1
2
3
4
5
6
7
8
9
10
11
12切换市列表,清空区的表单
const getDictList = async (id: number) => { console.log('city id: ', id); // 将区的表单值设置为undefined form.setFieldsValue({ districtCode:undefined }) const dictList = await getDistrictList(id); setDictList(dictList); }1
2
3
4
5
6
7
8
9
# 12. 医院列表分页功能
# 12-1. 接口相关类型封装
/**
* 医院列表参数类型
*/
export interface IHospitalListParams {
page: number;
limit: number;
hoscode?: string;
hosname?: string;
hostype?: string;
provinceCode?: string;
cityCode?: string;
districtCode?: string;
status?: number;
}
/**
* 医院列表每一项 类型
*/
export interface IHospitalItem {
id: string;
createTime: string; // 创建时间
param: {
hostypeString: string; // 医院等级
fullAddress: string; // 医院地址
},
hoscode: string; // 医院编号
hosname: string; // 医院名
hostype: string; // 医院类型
provinceCode: string; // 省
cityCode: string; // 市
districtCode: string; // 区
address: string; // 地址
logoData: string; // 医院logo base64URL
route: string; //乘车路线
status: number; // 医院状态
bookingRule: {
cycle: number; // 预约周期
releaseTime: string; // 放号时间
stopTime: string;// 停止挂号时间
quitDay: number; // 就诊结束日期
quitTime: string; // 结束时间
rule: string[]; //取号规则
}
}
/**
* 医院列表类型
*/
export type IHospitalList = IHospitalItem[]
/**
* 请求医院列表响应对象类型
*/
export interface IHospitalListResponse {
content:IHospitalList;
totalElements:number;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 12-2. api函数封装
/**
* 获取医院列表分页数据api方法
* @param param0
* @returns
*/
export const getHospitalList = ({page,limit,hoscode,hosname,hostype,provinceCode,cityCode,districtCode,status}:IHospitalListParams)=>{
return request.get<any, IHospitalListResponse>(`/admin/hosp/hospital/${page}/${limit}`, {
params:{
hoscode,
hosname,
hostype,
provinceCode,
cityCode,
districtCode,
status
}
})
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 12-3. 渲染医院列表及分页
- 定义分页相关状态
- 定义获取医院分页列表的async函数
- 定义useEffect 生命周期钩子并调用
- 给Table组件添加 rowKey dataSource
- 给columns 数组中的对应列配置对象,定义 dataIndex或 render
- 给table定义 pagination,实现分页
- 给useEffect添加监听 current, pageSize
- 给请求方法中的固定值参数,替换成 状态数据
# 12-4. 查询、清空功能
查询实现原理:
- 点击查询按钮,获取表单中的数据,用来重置状态数据
- 在useEffect中监听 表单中对应状态数据的变化,触发重新发送请求
- 请求的方法参数,都换成状态数据
# 12-4-1. 查询功能实现
- 定义form表单对应的状态
let [formFields, setFormFields] = useState<IFormFields>({
hoscode: undefined,
hosname: undefined,
provinceCode: undefined,
cityCode: undefined,
districtCode: undefined,
status: undefined,
hostype: undefined
})
2
3
4
5
6
7
8
9
- 给Form组件添加 onFinish方法,并绑定事件的回调函数
<Form onFinish={search}>
const search = () => {
setFormFields(form.getFieldsValue());// 获取表单数据最新的值,设置到formFields状态数据中
setCurrent(1);
}
2
3
4
5
6
- 监听 formFields中每一个值的变化,如果有改变,重新发送ajax请求
useEffect(() => {
console.log('重新发请求')
_getHospitalList();
}, [current, pageSize, formFields.hoscode, formFields.hosname, formFields.cityCode, formFields.provinceCode, formFields.districtCode, formFields.hostype, formFields.status])
2
3
4
- 修改_getHospitalList() 函数中的参数,带上状态数据 formFields
const _getHospitalList = async () => {
setLoading(true);
let { content, totalElements } = await getHospitalList({ page: current, limit: pageSize, ...formFields });
// 设置医院列表状态
setHospitalList(content);
setTotal(totalElements);
setLoading(false);
}
2
3
4
5
6
7
8
9
# 12-4-2. 清空功能实现
- 设置清空按钮 disabled 的禁用条件
- 给清空按钮绑定事件回调函数 clear
- clear中的逻辑
- 重置表单数据为空
- 重置状态数据 formFields 各项值为undefined
- 设置为当前页
- 按钮 disabled禁用条件
<Button disabled={Object.values(formFields).every(item => item === undefined)} onClick={clear}>清空</Button>
- clear 实现逻辑
const clear = () => {
// 清空form表单的数据
// 清空 formFields 状态的值都为 undefined
// 当前页设置为 1
form.resetFields();
setFormFields({
hoscode: undefined,
hosname: undefined,
provinceCode: undefined,
cityCode: undefined,
districtCode: undefined,
status: undefined,
hostype: undefined
})
setCurrent(1);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 13. 排班管理
# 13-1. 渲染科室列表
科室列表的渲染,需要将请求回来的数据处理成符合tree组件使用的数据,需要做如下配置:
- fieldsName:设置 key code children的映射关系
- expandedKeys:设置要默认展开的树节点
- disabled:true => 设置禁用的节点
- selectedKeys: 这只默认被选中的树节点
- onSelected: 点击切换树节点切换科室
let [departmentList, setDepartmentList] = useState<IDepartmentList>([]);
let [expandedKeys, setExpandedKeys] = useState<string[]>([]);// 一级科室depcode组成的数组
let [depname, setDepname] = useState<string>();
let [depcode, setDepcode] = useState<string>();
const _getDepartmentList = async ()=>{
let departmentList = await getDepartmentList(hoscode as string);
console.log('departmentList: ', departmentList);
// 禁用一级科室树节点,就是给所有的一级科室对象,添加一个disabled:true
departmentList = departmentList.map(item=>{
item.disabled = true;
return item;
})
// 展开所有的一级科室
// 1. 获取所有一级科室 depcode组成的数组
let expandedKeys = departmentList.map(item=>item.depcode)
console.log('expandedKeys', expandedKeys);
setExpandedKeys(expandedKeys);
setDepartmentList(departmentList);// 设置科室列表状态数据
// 处理默认选中科室
let depname = (departmentList[0].children as IDepartmentList)[0].depname;
let depcode = (departmentList[0].children as IDepartmentList)[0].depcode;
// console.log(depname);
// console.log(depcode);
// 设置科室名和科室code状态
setDepname(depname);
setDepcode(depcode);
}
useEffect(()=>{
hoscode && _getDepartmentList();
}, [])
// tree组件
<Tree
// onSelect={onSelect}
// onCheck={onCheck}
treeData={departmentList as []}
fieldNames={{
title:'depname',
key:'depcode'
}}
expandedKeys={expandedKeys}
selectedKeys={[depcode as string]}
onSelect={(selectedKeys:any,info:any)=>{
// console.log('selectedKeys: ', selectedKeys);
// console.log('info:', info);
// 重新设置depcode和depname
setDepcode(info.node.depcode);
setDepname(info.node.depname);
}}
/>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 13-2. 排班日期分页数据获取
排班日期分页数据,依赖于depcode,所以执行的时机是depcode如果发生改变,重新获取该科室的排班日期列表
# 13-2-1. api类型及函数封装
- 类型封装:
/**
* 排班日期每一项的类型
*/
export interface IBookingScheduleItem {
workDate: string;// 排班日期
dayOfWeek: string;//星期几
docCount: number;// 已预约人数
reservedNumber: number;//总预约数
availableNumber: number;// 剩余预约数
}
export type IBookingScheduleList = IBookingScheduleItem[];
/**
* 请求排班日期分页数据响应结果的类型
*/
export interface IScheduleResponse {
total: number;
bookingScheduleList: IBookingScheduleList;
baseMap: {
hosname: string;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- api函数封装
/**
* 获取医院科室排班日期分页列表数据
* @param page 当前页
* @param limit 每页几条
* @param hoscode 医院编号
* @param depcode 科室编号
* @returns
*/
export const getScheduleList = (page:number,limit:number,hoscode:string,depcode:string)=>{
return request.get<any,IScheduleResponse>(`/admin/hosp/schedule/getScheduleRule/${page}/${limit}/${hoscode}/${depcode}`)
}
2
3
4
5
6
7
8
9
10
11
# 13-2-2. api函数调用时机及状态定义
- 状态定义:
let [current, setCurrent] = useState<number>(1);
let [pageSize, setPageSize] = useState<number>(3);
let [total, setTotal] = useState<number>(10);
let [bookingScheduleList, setBookingScheduleList] = useState<IBookingScheduleList>([]);
2
3
4
- 调用时机
//获取医院科室 排班日期数据
const _getScheduleList = async ()=>{
let res = await getScheduleList(current,pageSize,hoscode as string, depcode as string);
console.log('res: ',res);
}
useEffect(()=>{
depcode && _getScheduleList();
},[depcode,current, pageSize]);
2
3
4
5
6
7
8
9
# 13-3. 医生列表渲染
# 13-3-1. 医生列表api类型及api函数定义
- api类型
/**
* 排班医生对象类型
*/
export interface IDoctorItem {
id: string;
createTime: string;
param: {
dayOfWeek: string;
depname: string;
hosname:string;
},
hoscode:string;
depcode: string;
title: string;
skill: string;
workDate: string;
reservedNumber: number;
availableNumber: number;
amount: number;
status: number;
}
//排班医生列表类型
export type IDoctorList = IDoctorItem[];
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- api函数封装
/**
* 获取排班医生列表
* @param hoscode
* @param depcode
* @param workDate
* @returns
*/
export const getDoctorList = (hoscode: string, depcode: string, workDate: string) => {
return request.get<any,IDoctorList>(`/admin/hosp/schedule/findScheduleList/${hoscode}/${depcode}/${workDate}`);
}
2
3
4
5
6
7
8
9
10
- 调用时机
// 获取排班医生列表数据
const _getDoctorList = async ()=>{
let doctorList = await getDoctorList(hoscode as string, depcode as string, workDate as string);
// console.log('doctorList: ', doctorList);
setDoctorList(doctorList);
}
useEffect(()=>{// 组件挂载完成之后执行 + workDate变化后执行
workDate && _getDoctorList();
}, [workDate]);
2
3
4
5
6
7
8
9
10
11
- 渲染:
<Table
className='mt'
pagination={false}
columns={columns}
dataSource={doctorList}
rowKey={'id'}
/>
2
3
4
5
6
7
# 14. 项目完成打包上线部署
- 构建最终目录:
npm run build===> build- 部署需要解决的问题:
- 404 ==》 index.html
- 配置静态资源目录
- 设置代理服务器完成跨域
const express = require('express');
const history = require('connect-history-api-fallback');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
// 0. 所有404的相应,使用 index.html替换
app.use(history());
// 1. 配置当前目录为静态资源目录
app.use(express.static('./'));
// 2. 进行跨域配置
app.use('/prod-api', createProxyMiddleware(
{
target: "http://syt-api.atguigu.cn", // 目标服务器地址
changeOrigin: true, // 允许跨域
pathRewrite: {
// 路径重写
"^/prod-api": "",
},
}
));
app.listen(5000, () => {
console.log('server run at 5000');
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 15. 复习
类组件
- state:
属性直接赋值:
构造函数:
- props:
this.props
事件处理函数
- this指向问题:
1. 包裹箭头函数 2. bind: 3. 直接定义成箭头函数:
怎么定义:
<button onClick={事件处理函数}></button>事件处理函数调用者:window
事件对象:
事件对象是一个合成的事件对象,做过兼容性处理。e.nativeEvent获取原生
如何得到事件对象? react会默认将第一个形参传事件对象
const click1 = (e)=>{ e 作为第一个形参,就可以接收到事件对象 } <button onClick={click1}>点击</button>1
2
3
4生命周期:
// componentDidMount 组件挂载后执行, 只会执行一次 发送ajax请求,开启定时器,订阅消息,绑定自定义事件 // componentDidUpdate 组件更新执行 render--》componentDidUpdate newprops setState forceUpdate ==> render 有机会执行多次 // componentWillUnmount 组件卸载前执行 只会执行一次 取消定时器、取消订阅、解绑自定义事件1
2
3
4
5
6
7
8插值表达式:
// 条件渲染: 在jsx模板中,只能使用三元表达式、逻辑运算 return ( <> <div>三元表达式:{条件?<div>111</div>:</div>222</div>}</div> <div>逻辑运算: {条件 && <div>222</div>}</div> <div>函数调用: {fn()} </div> </> )1
2
3
4
5
6
7
8函数组件:
state:useState
props: 形参
传递:
一个一个传:
<Child count={count} msg={msg}/>使用扩展运算符一起传:
let [user, setUser] = useState({ count:1, msg:'atguigu' }) <Child {...user}/>1
2
3
4
5
6事件处理函数:没有this问题 this-> undefined
生命周期:useEffect
// useEffect(()=>{// didMount 组件挂载调用一次 return ()=>{ // willUnmount 调用一次 } },[]) // useEffect(()=>{ }) useEffect(()=>{ },[count])1
2
3
4
5
6
7
8
9
10
11
12
13
14redux:
<Provider store={}> </Provider> useSelector useDispatch useDispatch(actionCreator(payload))==> useDispatch(action对象)1
2
3
4
5
6
7路由:
<BrowserRouter></BrowserRouter> <NavLink > <Link> useNavigate 创建编程式导航 路由表: useRoutes(路由表数组) path element children 路由参数: 1. useParams() path 2. useSearchParams() query 3. useLocation() state BrowserRouter NavLink Link Outlet from 'react-router'1
2
3
4
5
6
7
8
9
10
11创建一个根节点
const root = ReactDOM.createRoot(dom元素)1ref:
- 绑定在dom元素身上,作用 获取该dom元素
- 单独模拟 componentDidUpdate
- 给类组件绑定,获取类组件的实例对象
- 给函数组件绑定, React.forwardRef, 作用,父组件获取子组件的dom元素
受控组件非受控组件:
受控:表单元素收到了组件状态的控制
value、checked 赋值了状态就受控
只读
onChange 获取最新的用户输入 改变对应的状态
获取值:直接通过状态数据回去
非受控:
defaultValue、defaultChecked
获取值:通过ref 获取真实dom .value获取
redux/toolkit
创建切片: createSlice
name 属性==》切片名 必须的
initalState
reducer
配置仓库: configureStore
configureStore({ reducer:{ count:countSlice.reducer } })1
2
3
4
5获取仓库数据:store.getState()
改变仓库数据:
store.dispatch(actionCreator(payload)) ===> store.dispatch(action对象)1
2
3
# 16. 前端重要知识点

# 17. 未来三年
# 17-1. 学习:
# 17-2. 找工作
跟编码水平无关、跟记忆力、脸皮、韧性、心态关系重大
心态:
# 17-3. 工作前三个月
心法:这里是尚硅谷带薪实训基地【60窝囊废 + 40 技术】
三个月:
- 行业经验:
- 真实的项目经验:
- 编码能力,同行同事:
# 17-4. 半年后
# 17-5. 必须进大厂
- 学历:本科 买一个 学信网可查的 成人教育 2-3年 2. 3 ==》 1
- 年终奖:
# 附件
13141403113
react 中的事件对象 onClick={(e)=>{}} react自己合成是事件对象 e 做过兼容 e.nativeEvent
react 中的事件处理函数,参数的默认值是 当前组件实例对象
function send(e){
}
=>{ this
}}