Shu-How Zの小窝

Loading...

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组件 确认

http://geek.itheima.net,

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入门到实战完结篇

posted @ 2024-12-14 13:16  KooTeam  阅读(151)  评论(0)    收藏  举报