React18入门到实战视频
黑马程序员前端React18入门到实战视频教程,从react+hooks核心基础到企业级项目开发实战(B站评论、极客园项目等)及大厂面试全通关
https://www.bilibili.com/video/BV1ZB4y1Z7o8
P1 React入门到实战导学课程
2023
P2 Day1-01.React简单介绍
P3 Day1-02.React开发环境创建
create-react-app是一个快速 创建React开发环境的工具,底层由Webpack构建,封装了配置细节,开箱即用
npx create-react-app react-basic
P4 Day1-03.JSX基础-概念和本质
注意:if语句、switch语句、变量声明属于语句,不是表达式,不能出现在0中
P5 Day1-04.JSX基础-识别js表达式
P6 Day1-05.JSX基础-实现列表渲染
P7 Day1-06.JSX基础-实现基础条件渲染
P8 Day1-07.JSX基础-实现复杂条件渲染
P9 Day1-08.React中的事件绑定
P10 Day1-09.React组件基础使用
概念:一个组件就是用户界面的一部分,它可以有自己的逻辑和外观,组件之间可以互相嵌套,也可以复用多次
12
P11 Day1-10.useState基础使用
useState是一个React Hook(函数),它允许我们向组件添加一个状态变量,从而控制影响组件的渲染结果
P12 Day1-11.useState修改状态的规则
P13 Day1-12.基础样式控制
P14 Day1-13.评论案例-列表渲染
P15 Day1-14评论案例-删除功能实现
P16 Day1-15.评论案例-tab切换功能实现
P17 Day1-16.评论案例-排序实现
P18 Day1-17.classnames工具优化类名控制
classnames是一个简单的JS库,可以非常方便的通过条件动态控制class类名的显示
github.com/JedWatson/classnames
P19 Day2-01.表单受控绑定
P20 Day2-02.React中获取DOM
P21 Day2-03.发表评论-核心功能实现
P22 Day2-04.发表评论-id和时间处理
uuid dayjs
P23 Day2-05.发表评论-清空内容和聚焦实现
P24 Day2-06.组件通信-父传子-基础实现
P25 Day2-07.组件通信-父传子-props说明
父传子-props说明
1.props可传递任意的数据
数字、字符串、布尔值、数组、对象、函数、JSX
2.props是只读对象
子组件只能读取props中的数据,不能直接进行修改,父组件的数据只能由父组件修改
P26 Day2-08.组件通信-父传子-chilren说明
P27 Day2-09.父子组件通信-子传父实现
P28 Day2-10.使用状态提升实现兄弟组件通信
P29 Day2-11.使用context机制跨层传递数据
实现步骤:
1,使用createContext方法创建一个上下文对象Ctx
2.在顶层组件(App)中通过 Ctx.Provider 组件提供数据
3.在底层组件(B)中通过 useContext 钩子函数获取消费数据
import React, { Component, useContext } from 'react'
import './index.css'
let MyContext = React.createContext()
let { Provider,Consumer } = MyContext
export default class A extends Component {
state = {
name: 'koo',
age: 28
}
render() {
let { name, age } = this.state
return (
<div className='parent'>
A组件
<Provider value={{ name, age }}>
<B></B>
</Provider>
</div>
)
}
}
class B extends Component {
render() {
return (
<div className='child'>
B组件
<C></C>
</div>
)
}
}
//只能类组件使用
// class C extends Component {
// static contextType=MyContext
// render() {
// let {name,age}=this.context
// return (
// <div className='grand'>
// C组件
// <del>{name}-{age}</del>
// </div>
// )
// }
// }
// 函数和类组件使用
// function C() {
// return (
// <div className='grand'>
// C组件
// <Consumer>
// {
// value=><del>{value.name}-{value.age}</del>
// }
// </Consumer>
// </div>
// )
// }
//
function C() {
let msg=useContext(MyContext)
return (
<div className='grand'>
C组件
{msg}
</div>
)
}
P30 Day2-12.useEffect-概念理解和基础使用
useEffect 有sifai
useEffect 的概念理解
useEffect是一个React Hook函数,用于在React组件中创建不是由事件引起而是由渲染本身引起的操作,比如发送AJAX请求,更改DOM等等
接口地址:http://geek.itheima.net/v1_0/channels
P31 Day2-13.useEffect-不同依赖项说明
useEffect副作用函数的执行时机存在多种情况,根据传入依赖项的不同,会有不同的执行表现依赖项
副作用函数执行时机
没有依赖项 组件初始渲染+组件更新时执行
空数组依赖 只在初始渲染时执行一次
添加特定依赖项 组件初始渲染+特性依赖项变化时执行
P32 Day2-14.useEffect-清除副作用
useEffect—清除副作用
在useEffect中编写的由渲染本身引起的对接组件外部的操作,社区也经常把它叫做副作用操作,比如在useEffect中开启了一个定时器,我们想在组件卸载时把这个定时器再清理掉,这个过程就是清理副作用
P33 Day2-15.自定义Hook实现
概念:自定义Hook是以use打头的函数,通过自定义Hook函数可以用来实现逻辑的封装和复用
封装自定义hook通用思路
1.声明一个以use打头的函数
2.在函数体内封装可复用的逻辑(只要是可复用的逻辑)
3.把组件中用到的状态或者回调return出去(以对象或者数组)
4.在哪个组件中要用到这个逻辑,就执行这个函数,解构出来状态和回调进行使用美
P34 Day2-16.ReactHooks使用规则说明
ReactHooks使用规则
使用规则
1.只能在组件中或者其他自定义Hook函数中调用
2.只能在组件的顶层调用,不能嵌套在 if、for、其他函数中
P35 Day2-17.案例优化-使用useEffect获取数据
1.使用 json-server 工具模拟接口服务,通过 axios 发送接口请求
json-server是一个快速以.json文件作为数据源模拟接口服务的工具
axios是一个广泛使用的前端请求库
优化需求-自定义Hook函数封装数据请求
一般思路:
1.编写一个 use 打头的函数
2.函数内部编写封装的逻辑
3.return出去组件中用到的状态和方法
4.组件中调用函数解构赋值使用
P36 Day2-18.案例优化-自定义hook封装请求逻辑
P37 Day2-19.案例优化-评论Item组件封装
P38 Day3-01.Redux快速上手
什么是Redux?
Redux是React最常用的集中状态管理工具,类似于Vue中的Pinia(Vuex),可以独立于框架运行
P39 Day3-02.Redux与React-环境准备
在React中使用redux,官方要求安装俩个其他插件-Redux Toolkit 和 react-redux
1.Redux Toolkit(RTK)-官方推荐编写Redux逻辑的方式,是一套工具的集合集,简化书写方式
2,react-redux-用来链接Redux和React组件的中间件
npm i @reduxjs/toolkit react-redux
React 基础 - day03.rar reduxjs/toolkit
P40 Day3-03.Redux与React-实现counter
在React组件中使用store中的数据,需要用到一个钩子函数-useSelector,它的作用是把store中的数据映射到组件中,使用样例如下:
React组件中修改store中的数据需要借助另外一个hook函数-useDispatch,它的作用是生成提交action对象的dispatch函数,使用样例如下:
1.组件中使用哪个hook函数获取store中的数据?
useSelector
2.组件中使用哪个hook函数获取dispatch方法?
useDispatch
3,如何得到要提交action对象?
执行store模块中导出的actionCreater方法
P41 Day3-04.Redux与React-提交action传参
提交action传参实现需求
在reducers的同步修改方法中添加action对象参数,在调用actionCreater的时候传递参数,参数会被传递到action对象payload属性上
P42 Day3-05.Redux与React-异步状态操作
yuque.com/fechaichai/qeamqf/omg1xi#WqBIX
P43 Day3-06.Redux调试-devtools
React Developer Tools 4.27.2 (2/16/2023)
Redux DevTools 3.0.19
Vuejs devtools 6.5.0
P44 Day3-07.美团案例-案例演示和环境准备
1·克隆项目到本地(内置了基础静态组件和模版)
git clone http://git.itcast.ch/heimaqianduan/redux-meituan.git
3.启动mock服务(内置了json-server)
基本开发思路:使用RTK(Redux Toolkit)来管理应用状态,组件负责数据渲染和dispatch action
P45 Day3-08.美团案例-分类和商品列表渲染
P46 Day3-09.美团案例-点击分类激活交互实现
P47 Day3-10.美团案例-商品列表切换显示
P48 Day3-11.美团案例-添加购物车实现
P49 Day3-12.美团案例-统计区域功能实现
P50 Day3-13.美团案例-购物车列表功能实现
P51 Day3-14.美团案例-控制购物车显示和
P52 Day4-01.ReactRouter-快速开始
2.安装最新的 ReactRouter包
npm i react-router-dom
编程式导航是指通过'useNavigate,钩子得到导航方法,然后通过调用方法以命令式的形式进行路由跳转,比如想在登录请求完毕之后跳转就可以选择这种方式,更加灵活
P53 Day4-02.ReactRouter-抽象路由模块
P54 Day4-03.ReactRouter-路由导航跳转
P55 Day4-04.ReactRouter-导航跳转传参
P56 Day4-05.ReactRouter-嵌套路由配置
嵌套路由配置
实现步骤:
1.使用 children 属性配置路由嵌套关系
2.使用<Outlet/>组件配置二级路由渲染位置
P57 Day4-06.ReactRouter-默认二级路由配置
当访问的是一级路由时,默认的二级路由组件可以得到渲染,只需要在二级路由的位置去掉path,设置index属性为true
P58 Day4-07.ReactRouter-404路由配置
实现步骤:
1.准备一个NotFound组件2.在路由表数组的末尾,以*号作为路由path配置路由
404路由
场景:当浏览器输入url的路径在整个路由配置中都找不到对应的path,为了用户体验,可以使用404兜底组件进行渲染
P59 Day4-08.ReactRouter-两种路由模式
俩种路由模式
各个主流框架的路由常用的路由模式有俩种,history模式和hash模式,ReactRouter分别由createBrowerRouter和createHashRouter 函数负责创建
P60 Day4-09.记账本-功能演示和环境创建
环境搭建
使用CRA创建项目,并安装必要依赖,包括下列基础包
1.Redux状态管理-@reduxjs/toolkit、react-redux
2.路由-react-router-dom
3.时间处理-dayjs
4.class类名处理-classnames
5.移动端组件库-antd-mobile
6.请求插件-axios
react-bill-test 项目
P61 Day4-10.记账本-配置别名路径@
别名路径配置
1.路径解析配置(webpack),把@/解析为 src/
2.路径联想配置(VsCode),VsCode 在输入@/时,自动联想出来对应的 src/下的子级目录
CRA本身把webpack配置包装到了黑盒里无法直接修改,需要借助一个插件-craco
npm i -D @craco/craco
联想路径配置
VsCode的联想配置,需要我们在项目目录下添加jsconfig.json文件,加入配置之后VsCode会自动读取配置帮助我们自动联想提示
P62 Day4-11.记账本-数据Mock实现
什么是数据Mock在前后端分类的开发模式下,前端可以在没有实际后端接口的支持下先进行接口数据的模拟,进行正常的业务功能开发
1.前端直接写假数据 纯静态,没有服务
2.自研Mock平台 成本太高
3.json-server等工具 有服务,成本低
json-server实现数据Mock json-server是一个node包,可以在不到 30 秒内获得零编码的完整的Mock服务
P63 Day4-12.记账本-整体路由设计
P64 Day4-13.记账本-antD主题色定制
P65 Day4-14.记账本-Redux管理账目列表
P66 Day4-15.记账本-TabBar功能实现
P67 Day5-01.月度账单-统计区域-功能演示和结构搭建
P68 Day5-02.月度账单-统计区域-点击切换时间选择框
P69 Day5-03.月度账单-统计区域-点击确定切换时间...
P70 Day5-04.月度账单-统计区域-数据按月分组实现
react useMemo 数据二次处理
useMemo 和 useCallback 是 React 的内置 Hook,通常作为优化性能的手段被使用。他们可以用来缓存函数、组件、变量,以避免两次渲染间的重复计算
P71 Day5-05.月度账单-统计区域-计算选择月份之后..
P72 Day5-06.月度账单-统计区域-初始化渲染统计数据C
P73 Day5-07.月度账单-列表区域-单日统计列表实现
yuque.com/fechaichai/zohcch/dulpwnn4doy9owrg/edit#eRmmD
P74 Day5-08.月度账单-列表区域-单日账单列表渲染...
P75 Day5-09.月度账单-列表区域-点击切换账单展开...
P76 Day5-10.月度账单-账单类型图标组件封装
P77 Day5-11.新增账单-功能熟悉和结构搭建
P78 Day5-12.新增账单-支出和收入功能实现
P79 Day5-13.新增账单-新增表单实现
P80 Day5-14.新增账单-收尾优化
82
1.使用CRA创建项目
P81 Day6-01.使用CRA初始化项目环境
文件夹 作用
apis接口
assets静态资源
components通用组件
pages页面级组件
router 路由Router
store Redux状态
utils 工具函数
P82 Day6-02.安装scss包
SCSS是什么
SCSS是一种后缀名为.scss的预编译CSS语言,支持一些原生CSS不支持的高级用法,比如变量使用,嵌套语法等,使用SCSS可以让样式代码更加高效灵活
CRA项目中接入SCSS
1.npm install sass-D
2.测试.scss文件是否可用(嵌套语法)
直接安装就可以用了
P83 Day6-03.安装antDesign
P84 Day6-04.配置基础路由Router
P85 Day6-05.配置别名路径
yuque.com/fechaichai/iqbhsl/knOvdrw63btii8d7#decf0987
P86 Day6-06.使用gitee管理项目
react-jike-2023
P87 Day6-07.登录-准备静态结构
P88 Day6-08.登录-表单校验实现
frominput 可以设置正则匹配 antd
P89 Day6-09.登录-获取表单数据
P90 Day6-10.登录-封装request请求模块
P91 Day6-11.登录-redux管理token-编写样板代码
P92 Day6-12.登录-redux管理token-实现Token异步...
api apifox.com/apidoc/shared-fa9274ac-362e-4905-806b-6135df6aa90e/api-31967347
P93 Day6-13.登录-redux管理token-实现登录后续逻辑
P94 Day6-14登录-Token持久化
登录-Token持久化
P95 Day6-15.登录-封装Token的存取删方法
P96 Day7-01.Axios请求头注入Token
P97 Day7-02.根据Token控制路由跳转
HOC Component
具体要做什么事儿?
有些路由页面内的内容信息比较敏感,如果用户没有经过登录获取到有效Token,是没有权限跳转的,根据Token的有无控制当前路由是否可以跳转就是路由的权限控制
P98 Day7-03.Layout-结构创建和样式reset
necolas.github.io/normalize.css/
P99 Day7-04.Layout-二级路由配置
P100 Day7-05.Layout-点击菜单跳转路由
P101 Day7-06.Layout-根据当前路由路径高亮菜单
P102 Day7-07.Layout-展示个人信息
P103 Day7-08.Layout-退出登录实现
P104 Day7-09.Layout-处理token失效
Layout-处理Token失效
什么是Token失效?
为了用户的安全和隐私考虑,在用户长时间未在网站中做任何操作且规定的失效时间到达之后,当前的Token就会失效,一旦失效,不能再作为用户令牌标识请求隐私数据
P105 Day7-10.Home-Echarts基础图表渲染
P106 Day7-11.Home-Echarts组件封装实现
P107 Day7-12.拓展-API模块封装
拓展-API模块封装
现存问题
当前的接口请求放到了功能实现的位置,没有在固定的模块内维护,后期查找维护困难解决思路
把项目中的所有接口按照业务模块以函数的形式统一封装到apis模块中
P108 Day8-01文章发布-功能演示说明
P109 Day8-02.基础文章发布-准备基础结构
P110 Day8-03.基础文章发布-准备富文本编辑器
.安装 react-quill 文编辑器
18 严格模式 render二次
112
P111 Day8-04.基础文章发布-频道列表获取渲染
P112 Day8-05.基础文章发布-收集表单数据提交表单
P113 Day8-06.文章封面-上传文章封面基础实现
P114 Day8-07.文章封面-实现切换封面类型
P115 Day8-08.文章封面-控制上传图片的数量
P116 Day8-09文章封面-发布带封面的文章
P117 Day8-10.文章列表-功能描述和结构创建
P118 Day8-11.文章列表-通过自定义hook获取频道列表
P119 Day8-12.文章列表-渲染table表格
P120 Day8-13.文章列表-适配文章状态
可选的方案:
1.直接再写一遍
2.存到Redux中维护
3.使用自定义业务hook
P121 Day9-01.文章列表-筛选功能实现
P122 Day9-02.文章列表-分页功能实现
P123 Day9-03.文章列表-删除功能实现
P124 Day9-04.文章列表-携带id跳转到编辑页
P125 Day9-05.编辑文章-回填基础数据
P126 Day9-06.编辑文章-回填封面信息
P127 Day9-07.编辑文章-根据id适配编辑和新增状态
P128 Day9-08编辑文章-更新文章
P129 Day9-09.项目打包-基础打包和本地预览
P130 Day9-10.打包优化-配置路由懒加载
Popconfirm组件 确认
1.项目打包
打包指的是将项目中的源代码和资源文件进行处理,生成可在生产环境中运行的静态文件的过程打包命令:npm run build
什么是路由懒加载?
路由懒加载是指路由的JS资源只有在被访问时才会动态获取,目的是为了优化项目首次打开的时间
P131 Day9-11.打包优化-包体积可视化分析
打包优化-包体积分析
什么包体积分析?
通过可视化的方式,直观的体现项目中各种包打包之后的体积大小,方便做优化
source-map-explorer 包体积分析
P132 Day9-12.打包优化-CDN配置
什么是CDN?
CDN是一种内容分发网络服务,当用户请求网站内容时,由离用户最近的服务器将缓存的资源内容传递给用户
哪些资源可以放到CDN服务器?
体积较大的非业务JS文件,比如react,react-dom
1.体积较大,需要利用CDN文件在浏览器的缓存特性,加快加载时间
2.非业务JS文件,不需要经常做变动,CDN不用频繁更新缓存
配置排除打包 cdn引入
https://www.yuque.com/fechaichai/tzzlh1/cx1gyc
P133 Day10-01.useReducer
useReducer作用:和useState的作用类似,用来管理相对复杂的状态数据
// useReducer
import { useReducer } from "react"
// 1. 定义reducer函数 根据不同的action 返回不同的状态
function reducer (state, action) {
switch (action.type) {
case 'INC':
return state + 1
case 'DEC':
return state - 1
case 'SET':
return action.payload
default:
return state
}
}
// 2. 组件中调用useReducer(reducer, 0) => [state, dispatch]
// 3. 调用dispatch({type:'INC'}) => 通知reducer产生一个新的状态 使用这个新状态更新UI
function App () {
const [state, dispatch] = useReducer(reducer, 0)
return (
<div className="App">
this is app
<button onClick={() => dispatch({ type: 'DEC' })}>-</button>
{state}
<button onClick={() => dispatch({ type: 'INC' })}>+</button>
<button onClick={() => dispatch({ type: 'SET', payload: 100 })}>update</button>
</div>
)
}
export default App
P134 Day10-02.useMemo
useMemo
作用:在组件每次重新渲染的时候缓存计算的结果
useMemo 有sM莫
缓存:消耗非常大的计算
// useMemo
// 缓存: 消耗非常大的计算
import { useMemo, useState } from "react"
// 计算斐波那契数列之和
function fib (n) {
console.log('计算函数执行了')
if (n < 3)
return 1
return fib(n - 2) + fib(n - 1)
}
function App () {
const [count1, setCount1] = useState(0)
const result = useMemo(() => {
// 返回计算得到的结果
return fib(count1)
}, [count1])
// const result = fib(count1)
const [count2, setCount2] = useState(0)
console.log('组件重新渲染了')
return (
<div className="App">
this is app
<button onClick={() => setCount1(count1 + 1)}>change count1: {count1}</button>
<button onClick={() => setCount2(count2 + 1)}>change count2: {count2}</button>
{result}
</div>
)
}
export default App
P135 Day10-03.React.memo-基础使用
React.memo
作用:允许组件在Props没有改变的情况下跳过渲染
React组件默认的渲染机制:只要父组件重新渲染子组件就会重新渲染
// React.memo
import { memo, useState } from "react"
// 1. 验证默认的渲染机制 子跟着父一起渲染
// 2. memo进行缓存 只有props发生变化的时候才会重新渲染 (不考虑context)
const MemoSon = memo(function Son () {
console.log('我是子组件,我重新渲染了')
return <div>this is son</div>
})
// function Son () {
// console.log('我是子组件,我重新渲染了')
// return <div>this is son</div>
// }
function App () {
const [count, setCount] = useState(0)
return (
<div className="App">
<button onClick={() => setCount(count + 1)}>+{count}</button>
{/* <Son /> */}
<MemoSon />
</div>
)
}
export default App
P136 Day10-04.React.memo-props比较机制说明
React.memo-props的比较机制
机制:在使用memo缓存组件之后,React会对每一个prop使用Object.is比较新值和老值,返回true,表示没有变化
// React.memo props比较机制
// 1. 传递一个简单类型的prop prop变化时组件重新渲染
// 2. 传递一个引用类型的prop 比较的是新值和旧值的引用是否相等 当父组件的函数重新执行时,实际上形成的是新的数组引用
// 3. 保证引用稳定 -> useMemo 组件渲染的过程中缓存一个值
import { memo, useMemo, useState } from 'react'
const MemoSon = memo(function Son ({ list }) {
console.log('子组件重新渲染了')
return <div>this is Son {list}</div>
})
function App () {
const [count, setCount] = useState(0)
// const num = 100
const list = useMemo(() => {
return [1, 2, 3]
}, [])
return (
<div className="App">
<MemoSon list={list} />
<button onClick={() => setCount(count + 1)}>change Count</button>
</div>
)
}
export default App
P137 Day10-05.useCallback
useCallback
作用:在组件多次重新渲染的时候缓存函数
// useCallback
import { memo, useCallback, useState } from "react"
const Input = memo(function Input ({ onChange }) {
console.log('子组件重新渲染了')
return <input type="text" onChange={(e) => onChange(e.target.value)} />
})
function App () {
// 传给子组件的函数
const changeHandler = useCallback((value) => console.log(value), [])
// 触发父组件重新渲染的函数
const [count, setCount] = useState(0)
return (
<div className="App">
{/* 把函数作为prop传给子组件 */}
<Input onChange={changeHandler} />
<button onClick={() => setCount(count + 1)}>{count}</button>
</div>
)
}
export default App
P138 Day10-06.React-forwardRef
React.forwardRef
使用ref暴露DOM节点给父组件
import { forwardRef, useRef } from "react"
// 子组件
// function Son () {
// return <input type="text" />
// }
const Son = forwardRef((props, ref) => {
return <input type="text" ref={ref} />
})
// 父组件
function App () {
const sonRef = useRef(null)
const showRef = () => {
console.log(sonRef)
sonRef.current.focus()
}
return (
<>
<Son ref={sonRef} />
<button onClick={showRef}>focus</button>
</>
)
}
export default App
P139 Day10-07.uselnperativeHandle
uselnperativeHandle
通过ref暴露子组件中的方法
import { forwardRef, useImperativeHandle, useRef } from "react"
// 子组件
const Son = forwardRef((props, ref) => {
// 实现聚焦逻辑
const inputRef = useRef(null)
const focusHandler = () => {
inputRef.current.focus()
}
// 把聚焦方法暴露出去
useImperativeHandle(ref, () => {
return {
// 暴露的方法
focusHandler
}
})
return <input type="text" ref={inputRef} />
})
// 父组件
function App () {
const sonRef = useRef(null)
const focusHandler = () => {
console.log(sonRef.current)
sonRef.current.focusHandler()
}
return (
<>
<Son ref={sonRef} />
<button onClick={focusHandler}>focus</button>
</>
)
}
export default App
P140 Day10-08.Class类组件-基础结构
145
P141 Day10-09类组件生命周期函数
P142 Day10-10类组件的组件通信说明
类组件的生命周期函数
概念:组件从创建到销毁的各个阶段自动执行的函数就是生命周期函数
类组件的组件通信
概念:类组件和Hooks编写的组件在组件通信的思想上完全一致
P143 Day10-11.zustand-基础用法
zustand 路s等
极简的状态管理工具
官网 zustand-demo.pmnd.rs
// zustand
import { create } from 'zustand'
// 1. 创建store
// 语法容易出错
// 1. 函数参数必须返回一个对象 对象内部编写状态数据和方法
// 2. set是用来修改数据的专门方法必须调用它来修改数据
// 语法1:参数是函数 需要用到老数据的场景
// 语法2:参数直接是一个对象 set({ count: 100 })
const useStore = create((set) => {
return {
// 状态数据
count: 0,
// 修改状态数据的方法
inc: () => {
set((state) => ({ count: state.count + 1 }))
}
}
})
// 2. 绑定store到组件
// useStore => { count, inc }
function App () {
const { count, inc } = useStore()
return (
<>
<button onClick={inc}>{count}</button>
</>
)
}
export default App
P144 Day10-12.zustand-异步支持
zustand-异步支持
对于异步的支持不需要特殊的操作,直接在函数中编写异步逻辑,最后只需要调用set方法传入新状态即可
// zustand
import { useEffect } from 'react'
import { create } from 'zustand'
const URL = 'http://geek.itheima.net/v1_0/channels'
// 1. 创建store
// 语法容易出错
// 1. 函数参数必须返回一个对象 对象内部编写状态数据和方法
// 2. set是用来修改数据的专门方法必须调用它来修改数据
// 语法1:参数是函数 需要用到老数据的场景
// 语法2:参数直接是一个对象 set({ count: 100 })
const useStore = create((set) => {
return {
// 状态数据
count: 0,
// 修改状态数据的方法
inc: () => {
set((state) => ({ count: state.count + 1 }))
},
channelList: [],
fetchGetList: async () => {
const res = await fetch(URL)
const jsonRes = await res.json()
console.log(jsonRes)
set({
channelList: jsonRes.data.channels
})
}
}
})
// 2. 绑定store到组件
// useStore => { count, inc }
function App () {
const { count, inc, fetchGetList, channelList } = useStore()
useEffect(() => {
fetchGetList()
}, [fetchGetList])
return (
<>
<button onClick={inc}>{count}</button>
<ul>
{
channelList.map(item => <li key={item.id}>{item.name}</li>)
}
</ul>
</>
)
}
export default App
P145 Day10-13.zustand-切片模式
zustand-切片模式
场景:当单个store比较大的时候,可以采用切片模式进行模块拆分组合,类似于模块化
https://www.yuque.com/fechaichai/lqbhsl/sg7y72rp3gtws8zs
// zustand
import { useEffect } from 'react'
import { create } from 'zustand'
const URL = 'http://geek.itheima.net/v1_0/channels'
// store
// counterStore
// channelStore
// index.js
// 1. 拆分子模块 再组合起来
const createCounterStore = (set) => {
return {
// 状态数据
count: 0,
// 修改状态数据的方法
inc: () => {
set((state) => ({ count: state.count + 1 }))
},
}
}
const createChannelStore = (set) => {
return {
channelList: [],
fetchGetList: async () => {
const res = await fetch(URL)
const jsonRes = await res.json()
console.log(jsonRes)
set({
channelList: jsonRes.data.channels
})
}
}
}
const useStore = create((...a) => {
return {
...createCounterStore(...a),
...createChannelStore(...a)
}
})
function App () {
// 2. 组件使用
const { count, inc, fetchGetList, channelList } = useStore()
useEffect(() => {
fetchGetList()
}, [fetchGetList])
return (
<>
<button onClick={inc}>{count}</button>
<ul>
{
channelList.map(item => <li key={item.id}>{item.name}</li>)
}
</ul>
</>
)
}
export default App
P146 Day11-01.React+TS基础环境创建
vite v4.4.9
https://cn.vitejs.dev/guide/#scaffolding-your-first-vite-project
使用create-react-app构建react+ts项目(超详细): https://blog.csdn.net/qq_52569656/article/details/130602732
create-react-app my-app --template typescript
npm create vite@latest my-app -- --template react-ts
最近前端圈掀起了一阵 rust 风,凡是能用 rust 重写的前端工具就用 rust 重写,今天介绍的工具就是通过 rust 实现的 babel:swc,一个将 ES6 转化为 ES5 的工具。
P147 Day11-02.useState-自动推导
useState-自动推导
通常React会根据传入useState的默认值来自动推导类型,不需要显式标注类型
P148 Day11-03.useState-泛型参数
useState-传递泛型参数
useState本身是一个泛型函数,可以传入具体的自定义类型
import { useState } from 'react'
type User={
name:string
}
function App() {
const [count, setCount] = useState(0)
const [user,setUser]=useState<User>(()=>{
return {
name:'koo'
}
})
return (
<>
</>
)
}
export default App
P149 Day11-04.useState-初始值为null
useState-初始值为null当我们不知道状态的初始值是什么,将useState的初始值为null是一个常见的做法,可以通过具体类型联合null来做显式注解
import { useState } from 'react'
type User={
name:string
}
function App() {
const [user,setUser]=useState<User|null>(null)
setUser({
name:'koo'
})
return (
<>
{user?.name}
</>
)
}
export default App
P150 Day11-05.Props与TS-基础使用
props与TypeScript-基础使用
为组件prop添加类型,本质是给函数的参数做类型注解,可以使用type对象类型或者interface接口来做注解
// type Props={
// className:string
// }
interface Props{
className:string
id?:string
}
function Button(props:Props) {
return (
<div>App</div>
)
}
function App() {
return (
<>
<Button className="primary" id={'id'}></Button>
</>
)
}
export default App
P151 Day11-06.Props与TS-特殊的children属性
props与TypeScript-为children添加类型children是一个比较特殊的prop,支持多种不同类型数据的传入,需要通过一个内置的ReactNode类型来做注解
说明:注解之后,children可以是多种类型,包括:React.ReactElement、string、number、React.ReactFragment、React.ReactPortal、boolean、null、undefined
// type Props={
// className:string
import React from "react"
// }
interface Props{
className:string
id?:string
children:React.ReactNode
}
function Button(props:Props) {
return (
<div>{props.children}</div>
)
}
function App() {
return (
<>
<Button className="primary" id={'id'}>hello</Button>
</>
)
}
export default App
P152 Day11-07.props与TS-为事件prop添加类型
props与TypeScript-为事件prop添加类型组件经常执行类型为函数的prop实现子传父,这类prop重点在于函数参数类型的注解
interface Props{
goTo?:(msg:string)=>void
}
function Button(props:Props) {
let handle=()=>{
props.goTo?.('hello')
}
return (
<div onClick={handle}>click</div>
)
}
function App() {
return (
<>
<Button goTo={(msg)=>console.log(msg)}></Button>
</>
)
}
export default App
P153 Day11-08.useRef与TS
useRef与TypeScript-获取dom获取dom的场景,可以直接把要获取的dom元素的类型当成泛型参数传递给useRef,可以推导出.current属性的类型
可选链 前面不为空值(null/undefined)执行点运算
类型守卫 防止出现空值点运算错误
1.获取dom
2.稳定引用的存储器(定时器管理)
import { useEffect, useRef } from "react"
function App() {
let domRef=useRef<HTMLInputElement>(null)
let timer=useRef<number|undefined>(undefined)
useEffect(()=>{
domRef.current?.focus()
timer.current=setInterval(()=>console.log('hello'),1000)
return ()=>clearInterval(timer.current)
},[])
return (
<>
<input type="text" ref={domRef}/>
</>
)
}
export default App
P154 Day12-01.项目环境创建
P155 Day12-02.安装antDesignMobile
安装Ant Design Mobile
Ant Design Mobile是Ant Design家族里专门针对于移动端的组件库
P156 Day12-03.配置基础路由
P157 Day12-04.配置路径別名
https://www.yuque.com/fechaichai/lqbhsl/vxdwlotilold0tr4#yq9g1
vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
})
P158 Day12-05.axios插件安装配置
P159 Day12-06.API模块封装-axios配合ts使用
P160 Day12-07.Home模块-channels基础数据渲染
P161 Day12-08.Home模块-channels-hooks优化
P162 Day12-09.Home模块-List-列表数据获取渲染
P163 Day12-10.Home模块-List无限加载实现
Home模块-List列表无限滚动实现
P164 Day12-11.详情模块-路由跳转&数据渲染
P165 React入门到实战完结篇

浙公网安备 33010602011771号