《react上手教程》- 基础语法
# 1.环境安装
开发react项目需要安装电脑的底层框架,必须提前安装
node版本管理工具:
nvm
node底层版本:
18.x 16.x
三方包管理工具:
npm cnpm yarn pnpm
# 1.傻瓜式安装
- 所有nodejs历史版本列表
https:/zh-cn/download/releases/
选择稳定版本下载
傻瓜式 下一步 安装
检测是否安装成功 cmd 命令窗口
node -v #查看nodejs是否安装成功 且输出版本号
1
# 2.安装nvm管理node
可以任意切换nodejs的版本 nodejs版本管理工具安装
下载地址:https://github.com/coreybutler/nvm-windows/releases
// nvm 默认路径
C:\Users\admin\AppData\Roaming\nvm
//nodejs 默认路径
C:\Program Files\nodejs
2
3
4
# 1.安装nodejs
nvm install 18.0.0 #安装nodejs
nvm use 18.0.0 #切换到安装的nodejs版本
nvm uninstall 18.0.0 #卸载版本
nvm list #查看所有已经下载的node版本
2
3
4
# 2.npm 安装三方包的命令
npm install pnpm -g #全局安装pnpm
npm install yarn -g #全局安装yarn
npm install #项目根目录下运行之后 可以根据 package.json 文件下载所有的三方包
2
3
yarn #下载所有三方包
# 2.react 项目搭建
react 项目必须使用的
node版本>=16.x
# 2.1 脚手架 create-react-app
- 全局安装脚手架
npm install create-react-app -g
- 通过脚手架创建项目
create-react-app 项目名
- 启动项目
yarn start
# 2.2 脚手架 vite
尤雨溪团队研发,最新的前端脚手架工具 vite
,目的是取代前端项目打包构建市场的 webpack
而诞生
官网: https://cn.vitejs.dev/
- 创建react项目
--template
后面跟的是创建项目的模板,项目模板可以支持:
vanilla
,vanilla-ts
, vue
, vue-ts
,react
,react-ts
,react-swc
,react-swc-ts
,preact
,preact-ts
,lit
,lit-ts
,svelte
,svelte-ts
,solid
,solid-ts
,qwik
,qwik-ts
。
yarn create vite 项目名 --template react
或
npm create vite 项目名 --template react
或
pnpm create vite 项目名 --template reacte
2
3
4
5
- 安装项目中所有的三方依赖包
在项目根目录下运行 cmd 窗口
yarn
或
npm install
或
pnpm install
2
3
4
5
- 启动项目
yarn start
或
npm run start
或
pnpm run start
2
3
4
5
![运行效果](E:\教学\课件\react 体系化学习课件\react项目搭建\doc\img\3.png)
# 3.react 函数式组件基础语法 SFC
SFC:全称 Single File Component 单文件组件,指的是一个react单文件(jsx | tsx)组件的组成部分
- 函数式组件(主流)
// 引入react类
import React from 'react'
// 引入组件自己的样式文件
import './App.css'
// 暴露一个函数,该函数就是一个组价
export default function App() {
// 这个函数return的部分就会渲染到页面上
// return 后面必须跟的是一段html代码
return (
// return的节点上 必须 有且只有一个顶级节点
<div>App</div>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
- 类组件(老项目)
import React, { Component } from 'react'
// 暴露一个类 继承于Component 类
// 这个类的原型方法 render return 一段 html
export default class App extends Component {
render() {
return (
<div>
APP
</div>
)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
# 4.数据响应式
在函数式组件中 响应式数据定义hooks 使用的是 useState
useState 作用:
1.useState 是react 库中暴露的一个 函数,该函数返回了一个数组,数组中有两个参数.
2.useState 的一般用于定义一个响应式数据
3.响应式数据作用:当这个数据发生改变时,页面使用了这个数据的地方都会发生更新[即:数据改-->页面改]
4.获取useState 的数据一般是通过数组的解构获取,这样可读性更高。
基础语法:
const [变量名,更新变量值的函数] = useState('变量初始值');
const [name,setName] = useState('张三');
与 Ts 连用:
const [变量名,更新变量值的函数] = useState<变量数据类型>('变量初始值')
// 定义类型
interface User{
name:string,
age:number
}
export default function App() {
// useState后面跟<数据类型>
const [userList,setUserList] = useState<User[]>([{name:'张麻子',age:20}])
return (
<div>
<p>{userList[0].name}</p>
</div>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 5.事件处理3种方式
- 基础事件
const 事件执行函数 = ()=>{
//事件执行函数体
}
2
3
<div onClick={事件执行函数名}></div>
案例: 计数器实现
import React, { useState } from "react";
export default function App() {
// 定义数据
const [num, setNum] = useState(0);
// 递增事件
const add = () => {
setNum(num + 1);
};
// 递减事件
const reduce = () => {
setNum(num - 1);
};
return (
<div>
<h1>{num}</h1>
<button onClick={add}>递增</button>
<button onClick={reduce}>递减</button>
</div>
);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- 带参数的事件
<div onClick={()=>执行函数(传递的数据)}> 修改数据</div>
import React, { useState } from 'react'
export default function App() {
const [num,setNum] = useState(0)
// 三方函数接收参数并修改
const changeNum = (data:number)=>{
setNum(data)
}
return (
<>
<h1>{num}</h1>
<button onClick={()=>setNum(100)}>修改数据</button>
<button onClick={()=>changeNum(1000)}>通过一个三方函数修改数据</button>
</>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 传递事件对象与参数
<div onClick={(事件对象event)=>执行函数(事件对象event,传递的数据)}> 修改数据</div>
import React, { useState } from "react";
export default function App() {
const handleClick = (e:Event,data:number)=>{
console.log(data);
// 阻止事件冒泡
e.stopPropagation();
// 阻止浏览器默认行为
e.preventDefault();
}
return (
<>
<div className="box">
<div className="box1" onClick={(e)=>handleClick(e,1000)}>盒子1</div>
</div>
</>
);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 获取表单的数据
通过受控组件的change事件获取
const [account, setAccount] = useState("");
const [passwrod, setPassword] = useState("");
const loginBtn = () => {
let data = {
account,
passwrod,
};
console.log(data);
};
return (
<div>
<p>
账号:
<input
type="text"
value={account}
onChange={(e) => setAccount(e.target.value)}
/>
</p>
<p>
密码:
<input
type="password"
value={passwrod}
onChange={(e) => setPassword(e.target.value)}
/>
</p>
<button onClick={loginBtn}>登录</button>
</div>
);
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
通过useRef 获取dom节点 获取
export default function login() {
const accountRef = useRef(null);
const passwordRef = useRef(null)
const loginBtn = () => {
let data = {
account:accountRef.current!.value,
passwrod:passwordRef.current!.value
};
console.log(data);
};
return (
<div>
<p>
账号:
<input
type="text"
ref={accountRef}
/>
</p>
<p>
密码:
<input
type="password"
ref={passwordRef}
/>
</p>
<button onClick={loginBtn}>登录</button>
</div>
);
}
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
# 6.jsx 语法
import React from 'react'
export default function App() {
//return 后面的代码 jsx:js与html 混写
return <div>jsx语法</div>;
}
2
3
4
5
6
- jsx 注释
export default function App() {
return (
<div>
{/* 一段代码注释 */}
</div>
)
}
2
3
4
5
6
7
- 类名设置为 className
export default function App() {
return (
<div>
<div className="box">
</div>
</div>
)
}
2
3
4
5
6
7
8
9
- jsx 循环
export default function App() {
const [userList,setUserList] = useState([{name:'张三',age:20},{name:'李四',age:40}])
return (
<div>
{/* 循环输出 */}
{userList.map(item=>{
return (
<div className="row">
{item.name}---{item.age}
</div>
)
})}
</div>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- jsx 判断
可以利用
&&
运算进行判断可以利用
条件?表达式1:表达式2
三目运算进行判断
export default function App() {
const [num,setNum] = useState(58);
return (
<div>
{ num>=80 && <div>优秀</div>}
{ num>=70 && num<80 && <div>良好</div>}
{ num>=60 && num<70 && <div>及格</div>}
{ num<60 && <div>不及格</div>}
</div>
)
}
2
3
4
5
6
7
8
9
10
11
export default function App() {
const [num,setNum] = useState(58);
return (
<div>
{
num>90?<div>优秀</div>:
num>80?<div>良好</div>:
num>70?<div>及格</div>:
num>60?<div>及格</div>:
<div>不及格</div>
}
</div>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
- 动态类名 与样式切换
案例:开关灯案例
App.tsx
import React, { useState } from 'react'
import './App.css'
export default function App() {
const [boxClass,setBoxClass] = useState('bg')
return (
<div className={boxClass}>
<button onClick={()=>setBoxClass('bg open')}>开灯</button>
<button onClick={()=>setBoxClass('bg close')}>关灯</button>
</div>
)
}
2
3
4
5
6
7
8
9
10
11
12
App.css
html,body,#root,.bg{
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.open{
background-color: #f44;
}
.close{
background-color: skyblue;
}
2
3
4
5
6
7
8
9
10
11
12
13
- 综合练习
tab栏切换,实现antd 标签切换的选中效果:
链接: https://ant.design/components/tabs-cn#tabs-demo-icon
# 5.useEffect hooks
useEffect 接受两个参数,useEffect (执行函数,[依赖项])
执行函数:函数体中 发送 ajax 并通过 useState解构的方法 更新数据
依赖项:值必须是一个数组,通知react 在哪些数据发生变更时,执行useEffect 的执行函数
useEffect (执行函数); //进入页面执行一次,每次render执行一次
useEffect (执行函数,[]); //进入页面执行一次,以后再也不执行,不依赖props 和 state中的数据进行触发
useEffect (执行函数,[num]); //进入页面执行一次,num发生改变执行一次
2
3
- 注意事项:
直接在useEffect中修改数据,每次render都会执行一次,num每次改变都会重新执行一次useEffect,形成死循环
const [num,setNum] = useState(0)
useEffect(()=>{
setNum(num+1)
})
2
3
4
修改方案1: 通过依赖项限制useEffect 执行次数
const [num,setNum] = useState(0)
useEffect(()=>{
setNum(num+1)
},[]) //不依赖任何数据 只会在进入页面执行一次
2
3
4
修改方案2: 只让这个数据更改一次
const [num,setNum] = useState(0)
useEffect(()=>{
setNum(1000); //传递一个固定值,执行了useEffect 之后不会进行第三次触发,第二次仍然会触发,但是数据没改变,第三次就不会运行
})
2
3
4
- useEffect 使用场景
1.代替生命周期,需要进入页面立即执行的代码 放在里面,例如:请求数据 axios代码
2.分页列表,table表格数据请求等场景,可以设置依赖项为pageNum
total
pageSize
搜索条件的form数据
用户改变了分页数据,查询数据之后自动重新发起请求并改变数据
3.useEffect 可以return 一个函数,里面的代码会在当前组件被卸载时自动执行,相当于类组件的销毁周期,全局事件的清除
useEffect(() => {
const handleResize = () => {
// 处理窗口大小变化...
};
window.addEventListener('resize', handleResize);
// 返回一个清理函数-卸载组件时自动执行
return () => {
window.removeEventListener('resize', handleResize);
}
}, []);
2
3
4
5
6
7
8
9
10
11
12
# 6.组件化概念与应用
组件化:react 是第一个提出组件化概念的前端框架
组件:代表着页面中某一个独立的功能块的代码块拆分出来写成一个个独立的文件
组件分类:页面级组件 ,业务组件,公共组件
组件的作用:
- 降低整体代码的复杂度,提升代码的可读性和可维护性
- 提升局部代码的可复用性
规范:
1.页面级组件必须放在
pages/
或views/
目录下,组件名建议大写2.业务组件放在该页面级组件的目录附近
components/
或该页面的目录下的其他子目录下3.公共组件必须放在项目
src/components
下,建议组件名大写
使用口诀: 1创 2导 3使用 4传值
- 父组件
import React from 'react'
// 导入子组件
import Son from '../components/Son/Son'
export default function App() {
return (
<div>
{/* 使用子组件 */}
<Son />
</div>
)
}
2
3
4
5
6
7
8
9
10
11
12
- 子组件
import React from "react";
export default function Son(){
return (
<div>我是子组件</div>
)
}
2
3
4
5
6
# 7.组件通信基础与规范
# 7.1 父传子
- 父组件
父组件通过 静态或动态属性传递数据
export default function App() {
const [userInfo, setUserInfo] = useState({ name: "张三", grade: 95 });
return (
<div>
<Child
title="我是爸爸组件传递的标题"
age={20}
userInfo={userInfo}
></Child>
</div>
);
}
2
3
4
5
6
7
8
9
10
11
12
- 子组件
子组件通过 函数形参 props 接收数据,
import React from "react";
export default function child(props: any) {
const { title, age, userInfo } = props;
return (
<div>
<h1>我是子组件</h1>
<h2>{title}</h2>
<h3>{age}</h3>
<h4>成绩:{userInfo.grade}</h4>
</div>
);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 7.2 子传父
- 父组件
父组件传递给 子组件一个 执行函数 ,等待子组件的调用传值【利用回调函数的特性】
import Child from "./components/Child";
export default function App() {
const [childData, setChildData] = useState(0);
const childChangeData = (data: number) => {
setChildData(data);
};
return (
<div>
<h1>{childData}</h1>
<Child send={childChangeData}></Child>
</div>
);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
- 子组件
子组件接收这个执行函数,在需要给父组件传值的地方,调用这个执行函数并传递数据
export default function child(props: any) {
const { send } = props;
const handleClick = () => {
send(1000);
};
return (
<div>
<button onClick={handleClick}>点击传递数据</button>
</div>
);
}
2
3
4
5
6
7
8
9
10
11
12
# 7.3 规范
react 的数据传递是单向数据流,父组件的数据发生改变,其所有使用了这个数据的 子组件 孙子组件 都会重新渲染
单向数据流:只有传递方才能够修改该数据的值,接收方不能修改数据值
# 8.路由概念 react-router-dom
路由是页面与页面之间跳转的映射关系体现的数据
一般情况下 : 用户访问的路由地址会一一对应到一个页面级组件的地址
- 项目根目录里 运行cmd 下载三方包
npm install react-router-dom
或
yarn add react-router-dom
或
pnpm install react-router-dom
2
3
4
5
- HashRouter
作用:包裹整个应用,一个React应用只需要使用一次
两种常用Router:BrowerRouter和HashRouter(history和hash路由)
- Link
作用:用于指定导航链接,完成路由跳转
语法说明:组件通过to属性指定路由地址,最终会渲染为a链接元素
- Routes
作用:提供一个路由出口,满足条件的路由组件会渲染到组件内部 相当于老版本:Switch
- Route
作用:用于指定导航链接,完成路由匹配
语法说明:path属性指定匹配的路径地址,element属性指定要渲染的组件
# 8.1 配置式路由
import React from 'react'
import { HashRouter, Routes, Route, Link } from 'react-router-dom'
import './App.scss'
import Home from './home/Home'
import Recommend from './home/Recommend'
import Goods from './home/Goods'
import Mine from './mine/Mine'
import Order from './order/Order'
import NotFound from './404/NotFound'
//根组件
export default function App() {
return (
<div>
{/* 路由配置 */}
<HashRouter>
{/* link 导航 类似于 a标签 */}
<div className="nav">
<Link to='/home'> 首页 </Link>
<Link to="/order"> 订单 </Link>
<Link to='/mine'> 我的</Link>
</div>
{/* 定义层级路由 */}
<Routes>
{/* 默认打开 访问home index索引路由不能有子路由 */}
<Route index element={<Home/>}></Route>
<Route path='/home' element={<Home />}>
{/* 子路由定义 index 表示默认打开的子页面 */}
<Route index element={<Recommend />}></Route>
<Route path='/home/goods' element={<Goods />}></Route>
</Route>
<Route path='/order' element={<Order />}></Route>
<Route path='/mine' element={<Mine />}></Route>
{/* 404 路由 */}
<Route path='*' element={<NotFound/>}></Route>
</Routes>
</HashRouter>
</div>
)
}
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
# 8.2 约定式路由
创建一个独立的路由配置文件
src/router/index.tsx
该文件导入createHashRouter
创建一个路由对象数组,并暴露出去在主模块
main.tsx
中导入该数组,并通过RouterProvider
组件router
属性 使用这个数组就可以全局生效
步骤: 1创 2配 3占位 4.全局导 5测试
src/router/index.tsx
import {createHashRouter,Navigate} from 'react-router-dom'
import Layout from "../pages/layout";
import Login from '../pages/login'
import UserList from "../pages/users/list";
import UserCenter from "../pages/users/center";
import UserEditPwd from '../pages/users/editPwd'
import UserAdd from '../pages/users/add'
const router = createHashRouter([
{
path:'/',
element:<Navigate to={'/login'} />
},
{
path:'/login',
element:<Login />
},
{
path:'/user',
element:<Layout/>,
children:[
{
index:true,
element:<UserList />
},
{
path:'/user/center',
element:<UserCenter />
},
{
path:'/user/editPwd',
element:<UserEditPwd />
},
{
path:'/user/Add',
element:<UserAdd />
}
]
}
])
export default router;
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
- main.tsx
<RouterProvider router={router}>
<App />
</RouterProvider>
2
3
- layout.tsx 给子路由占位
import { Outlet } from "react-router-dom";
export default function layout() {
return (
<div>
layout
{/* 给子路由占位 子路由出口 */}
<Outlet />
</div>
);
}
2
3
4
5
6
7
8
9
10
11
# 8.3 访问路由
- 通过 Link 组件访问
<Link to='/mine'> 我的</Link>
- 通过 js访问 【编程式导航】
通过 react-router-dom 的钩子函数 useNavigate 进行跳转
import React from 'react'
//导入跳转钩子函数
import {useNavigate } from 'react-router-dom';
export default function Order() {
//调用钩子函数 返回一个跳转函数
const navigate = useNavigate();
//实现跳转事件
const toGoods = ()=>{
//跳转时 不加入历史记录栈中 需额外设置replce 为true
navigate('/home/goods',{replace:true})
}
return (
<div>Order
<button onClick={toGoods}>前往商品列表</button>
</div>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 8.4 跨页面传值
路由跳转携带参数(两种方式:searchParams和params)
- searchParams
navigate('/goods?id=1000')
接收参数
import {useSearchParams} from 'react-router-dom'
let [params] = useSearchParams();
console.log(params.get('id'));
2
3
4
- params
navigate('/goods/10000')
接受参数
import {useParams} from 'react-router-dom'
let params = useParams();
console.log(params.id);
2
3
4
配置/注册路由 的代码需要修改 App.jsx
<Route path='/home/goods/:id' element={<Goods />}></Route>
# 8.5 关于路由的 hooks
优先级从上至下
useNavigate (opens new window) - 通常在loader和action中使用redirect
useLocation (opens new window) - 返回当前的location对象
useSearchParams (opens new window) - useSearchParams的网络版
useParams (opens new window) - 返回一个由当前URL的动态参数
useMatch (opens new window) - 返回相对于当前位置的给定路径上的路由的匹配数据
useMatches (opens new window) - 返回页面上的当前路由匹配
useActionData (opens new window) - hooks提供前一个导航的action结果的返回值
useAsyncError (opens new window) - 返回最近的Await组件的拒绝值
useAsyncValue (opens new window) - 返回最近的Await ancestor组件的解析数据
useBeforeUnload (opens new window) - 只是window.onbeforeunload的一个辅助工具
useFetcher (opens new window) - 该功能只有在使用数据路由器时才有效
useFetchers (opens new window) - 返回一个所有inflight fetchers的数组
useFormAction (opens new window) - 在Form内部使用,以自动解决上下文中的默认action和相对action,以适应当前路由
useHref (opens new window) - 返回一个URL,可以用来链接到给定的to位置
useInRouterContext (opens new window) - 如果组件在Router的上下文中被渲染,返回true否则返回false
useLinkClickHandler (opens new window) - 返回一个点击事件处理程序用于导航
useLinkPressHandler (opens new window) - 返回自定义Link导航的按下事件处理程序
useLoaderData (opens new window) - 提供了从你的路由loader返回的值
useNavigation (opens new window) - 以便在数据Mutations上建立待定的导航指标和Optimistic UI
useNavigationType (opens new window) - 返回当前的导航类型或者用户是如何来到当前页面的或者通过历史栈上的弹出、推送或替换action
useOutlet (opens new window) - 返回路由层次结构中这一层的子路由的元素
useOutletContext (opens new window) - 创 - 建你自己的context provider
useResolvedPath (opens new window) - 给定的to值中的pathname与当前位置的路径名进行对比
useRevalidator (opens new window)允许你以任何理由重新验证数据
useRouteError (opens new window) - 返回在action、loader或渲染过程中抛出的任何东西
useRouteLoaderData (opens new window) - 任何当前渲染的路由的数据在tree中的任何地方都可用
useRoutes (opens new window) - 返回值是一个有效的React元素
useSearchParams (RN) (opens new window) - useSearchParams的React Native版本
useSubmit (opens new window) - Form的命令式版本
# 9.组件通信-状态管理库 redux-toolkit
状态管理库:存储数据的仓库
主要应用于 多个无关系组件的数据共享
- 安装
yarn add @reduxjs/toolkit react-redux
或
npm i @reduxjs/toolkit react-redux
或
pnpm i @reduxjs/toolkit react-redux
2
3
4
5
- 创建模块文件
用户模块的数据存储文件
src/store/modules/userSlice.tsx
通过 ‘@redux-toolkit’ 包中的 createSlice 方法 创建一个存储对象
创建时传入一个对象,包含:
name
,initialState
reducers
三个属性暴露两个东西: 修改数据的方法 创建的子模块
import {createSlice} from '@reduxjs/toolkit'
const userSlice = createSlice({
name:'user',
initalState:{
userId:'',
token:'',
userInfo:{}
},
reducers:{
changeUserInfo(state,{payload}){
state.userId = payload.userId;
state.token = payload.token;
state.userInfo = payload
}
}
})
//暴露修改数据的方法
export const {changeUserInfo} = userSlice.actions;
//暴露子模块整体
export default userSlice.reducer;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- store 配置
创建
src/store/index.tsx
通过
@redux/toolkit
导入configureStore
对整个项目的状态管理库进行配置导入子模块
通过
configureStore
方法 创建一个store对象创建对象时 传入
reducer
并配置子模块把这个store对象暴露出去,等待全局注入生效
import { configureStore } from "@reduxjs/toolkit";
//导入子模块
import userSlice from './modules/userSlice'
const store = configureStore({
reducer:{
userSlice
}
})
//暴露store仓库对象
export default store;
2
3
4
5
6
7
8
9
10
11
- 主模块注入
main.tsx
通过
react-redux
的Provider
组件的store
属性 进行全局注入
//导入配置好的仓库文件
import {Provider} from 'react-redux'
import store = './store'
{/* 全局注入store */}
<Provider store={store}>
<App />
</Provider>
2
3
4
5
6
7
8
- 页面组件使用数据
使用
react-redux
的useSelector()
hook 获取state数据
import {useSelector} from 'react-redux'
//获取数据
const {userInfo} = useSelector(store=>store.userSlice)
2
3
4
- 页面组件修改数据
使用
react-redux
的useDispatch()
hook 派发事件 与提交数据提交数据时,需要导入子模块中定义好的 修改数据的方法
import {useDispatch} from 'react-redux'
//导入修改方法
import {changeUserInfo} from '../store/modules/userSlice'
//修改数据
const dispatch = useDispatch()
let data = {
name:'拉拉',
age:20,
token:'xxx11122'
}
//提交修改数据
dispatch(changeUserInfo(data))
2
3
4
5
6
7
8
9
10
11
12
13
# 10.UI库-ant design 使用
# 1.官方文档阅读
官网地址:https://ant-design.antgroup.com/index-cn
快速上手官方教程:https://ant-design.antgroup.com/docs/react/getting-started-cn
- 安装antd
npm i antd
或
yarn add antd
或
pnpm i antd
2
3
4
5
- 使用组件
在任意react 页面组件中进行使用的方法
import {Button} from 'antd'
export default function center() {
return (
<div>
<Button type='primary'>点击按钮</Button>
</div>
)
}
2
3
4
5
6
7
8
- 常用组件使用
Button 按钮
Icon 图标
Form 表单 -表单验证
Input 输入框
Menu 菜单
Table 表格
Tabs 标签
# 2.关于antd form表单数据获取
# 1.受控组件直接获取
<Form onFinish={onFinish}>
<Form.Item name="account" >
<Input />
</Form.Item>
<Form.Item name="password" >
<Input/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit"> 立即登录</Button>
</Form.Item>
</Form>
2
3
4
5
6
7
8
9
10
11
const onFinish = (e)=>{
console.log(e) //{account:xxx,password:xxx}
}
2
3
# 2.通过ref dom 获取
获取到form表单的refdom 之后有非常的内置方法,便于操作form表单
//调用方式
formRef.current.方法名
2
方法 | 作用 |
---|---|
formRef.current.getFieldValue('key') | 获取表单内某个Input的值 |
formRef.current.getFieldsValue() | 获取表单的所有数据 直接返回数据对象 |
formRef.current.resetFields() | 重置表单数据 |
formRef.current.setFieldValue('key','value') | 设置表单中某个input的值 |
formRef.current.submit() | 触发表单的onFinish 事件,和受控组件的按钮相同效果 |
<Form ref={formRef}>
<Form.Item name="account">
<Input/>
</Form.Item>
<Form.Item name="password">
<Input />
</Form.Item>
</Form>
<Button type="primary" onClick={loginBtn}> 立即登录</Button>
2
3
4
5
6
7
8
9
10
const formRef = useRef(null);
//通过then 获取异步校验结果数据
const loginBtn = () => {
formRef.current.validateFields().then(res=>{
console.log(res);
})
};
//通过异步转同步 获取数据
const loginBtn = async ()=>{
let res = await formRef.current.validateFields();
console.log(res)
}
2
3
4
5
6
7
8
9
10
11
12
13
# 3.通过useForm hooks 获取
Form.useForm() 是封装自useRef方法,所以实现的思路完全一致
<Form form={formRef}>
<Form.Item name="account">
<Input/>
</Form.Item>
<Form.Item name="password">
<Input />
</Form.Item>
</Form>
<Button type="primary" onClick={loginBtn}> 立即登录</Button>
2
3
4
5
6
7
8
9
const [formRef] = Form.useForm() //类似于 const formRef = useRef(null)
const loginBtn = () => {
console.log(formRef); //操作方式比useRef 更简洁
formRef.getFieldsValue() //获取所有的数据
};
2
3
4
5
# 3.表单校验
- 标准校验
<Form.Item
name="account"
rules={[
{ required: true, message: "请输入账号" },
]}
>
<Input />
</Form.Item>
2
3
4
5
6
7
8
- 自定义校验
<Form.Item
name="account"
rules={[
{ required: true, message: "请输入账号" },
{ validator: vilidateAccount },
]}
>
<Input />
</Form.Item>
2
3
4
5
6
7
8
9
const vilidateAccount = (rule, value) => {
if (!value || value.length < 6) {
return Promise.reject(new Error("输入的数据长度不正确")); //校验规则不通过
}
return Promise.resolve(); //校验通过
};
2
3
4
5
6
- 自定义校验 获取其他的输入框的值与当前输入框进行比较
const vilidateAccount = (rule, value) => {
//在此获取form表单中其他的输入框的值 useForm实例获取
formRef.getFieldValue('password')
//通过useRef获取
formRef.current.getFieldValue('password')
if (!value || value.length < 6) {
return Promise.reject(new Error("输入的数据长度不正确"));
}
return Promise.resolve();
};
2
3
4
5
6
7
8
9
10
11
# 11.管理系统布局分析与处理-响应式布局处理
# 12.axios 三层封装
后端服务器地址:
http://115.159.153.85:8099
# 10.跨域处理与本地代理
# 11.TypeScript 在项目中的使用
# 13.用户角色与用户动态权限配置
# 14.移动端H5开发 antdesin mobile 库
# 15.移动端 APP 与 小程序开发 Taro库
# 16.数据大屏-数据可视化 -echarts
# 20.服务器运维-网站上线-APP上线
# 9月份
- 模拟面试
- 简历
- 找工作 的辅导
# 练习项目资料:
- 前端体验地址
http://sell-web-1254150235.cos-website.ap-chongqing.myqcloud.com/
- 服务器地址
http://115.159.153.85:8099