JSX是js和html的缩写,表示在js代码中编写html模板结构
JSX可通过{}识别js中的表达式(如变量,函数调用,方法等)
注意:if语句,switch语句,变量声明属于语句,不是表达式,不能出现在{}中
条件渲染:可以通过逻辑与&& 三元表达式?:实现基础的条件渲染
讯享网
on+事件名称={事件处理程序} 整体上遵循驼峰命名法
使用事件对象参数
传递自定义参数 (注意:不能直接写函数调用,这是事件绑定需要一个函数引用)

同时传递事件对象和自定义参数

在React中,一个组件就是首字母大写的函数,内部存放了组件的逻辑和视图UI,渲染组件只需要把组件当成标签书写


修改对象状态
对于对象类型的状态变量,传给set方法一个全新的对象来进行修改



父子通信
父传子
父组件传递数据 - 子组件标签上绑定属性
子组件接收数据 - 子组件通过props参数接收数据


子传父
在子组件中调用父组件的函数并传递参数

兄弟通信
状态提升实现兄弟组件通信
讯享网
跨层通信
用于在React组件中创建不是由事件引起而是由渲染本身引起的操作(副作用),比如发送AJAX请求,更改DOM等等



自定义hook函数以use打头的函数
注意:
只能在组件中或者其它自定义Hook函数中调用
只能在组件的顶层调用,不能嵌套在if,for,其它函数中



export {increment,decrement} 供组件使用
export default counterReducer 共index.js整合

异步修改








默认二级路由设置 二级路由的path去掉,将index属性设为true


两种路由模式

讯享网1. 多处用到,封装token的存取删方法 setToken,getToken,removeToken在utils/token.js中 2. axios拦截,请求头中注入token 3. Axios拦截401状态码,清除失效token,跳转登录
项目打包:指将项目中的源代码和资源文件进行处理,生成 可在生成环境运行的静态文件的过程 npm run build 本地预览(模拟服务器运行项目) 本地预览:指在本地通过静态服务器模拟生产服务器运行项目的过程 1.安装本地服务包 npm i -g serve 2.Serve -s https://blog.csdn.net/2301_/article/details/build 3.浏览器中访问 http://localhost:3000/
路由懒加载
- 把路由修改为由React提供的 lazy 函数进行动态导入
- 使用React内置的 Suspense组件 包裹路由中element选项对应的组件
包体积分析
讯享网通过可视化的方式,直观的体现项目中各种包打包之后的体积大小,方便做优化
- 安装包 source-map-explorer
- 配置命令指定要分析的js文件
CDN优化
CDN是一种内容分发网络服务,当用户请求网站内容时,由离用户最近的服务器将缓存的资源内容传递给用户 哪些资源可以放到CDN服务器? 体积较大的非业务JS文件, 比如react、react-dom
- 体积较大,需要利用CDN文件在浏览器的缓存特性,加快加载时间
- 非业务JS文件,不需要经常做变动,CDN不用频繁更新缓存 项目中怎么做?
useReducer
讯享网和useState的作用类似,用来管理相对复杂的状态数据 基础用法
- 定义一个reducer函数(根据不同的action返回不同的新状态)
- 在组件中调用useReducer,并传入reducer函数和状态的初始值
- 事件发生时,通过dispatch函数分派一个action对象(通知reducer要返回哪个新状态并渲染UI)


useMemo
作用:在组件每次重新渲染的时候缓存计算结果 原因:计算属性中,不是其依赖的值,发送变化时,计算属性也会进行再次计算(存在性能问题)

memo
讯享网作用:允许组件在Props没有改变的情况下跳过渲染 React组件默认的渲染机制:只要父组件重新渲染子组件就会重新渲染(如果子组件本身并不需要做渲染更新,存在浪费)


// 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 = 100const 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


forwardRef

讯享网// 子组件 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> </>
) }
useInperativeHandle
通过ref暴露子组件中的方法

// 子组件 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> </>
) }
讯享网// 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
// 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() 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
// 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() 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
基于vite创建开发环境
npm create vite@latest react-ts-pro – –template react-ts
npm create vite@latest 固定写法 (使用最新版本vite初始化项目)
react-ts-pro 项目名称 (可以自定义)
– –template react-ts 指定项目模版位react+ts
useState与TS
useState - 自动推导 (会根据传入useState的默认值自动推导类型,不需要显示标注类型) const [value,toggle] = useState(false)
- value: 类型为boolean
- toggle: 参数类型为boolean
讯享网useState - 传递泛型参数 (useState本身是一个泛型函数,可以传入具体的自定义类型) type User = { name:string, age:number } const [user,setUser] = useState<User>() useState - 初始值为null 当我们不知道状态的初始值是什么,将useState的初始值为null是一个常见的做法,可以通过具体类型联合null来做显式注解 type User = { name:string, age:number } const [user,setUser] = useState<User | null>(null) 事件与TS
讯享网为事件回调添加类型 为事件回调添加类型约束需要使用React内置的泛型函数来做,比如最常见的鼠标点击事件和表单输入事件

通过泛型函数约束了整个事件回调函数的类型,主要是为了约束事件参数e的类型
props与TS
为组件prop添加类型,本质是给函数的参数做类型注解,可以使用type对象类型或者interface接口来做注解 type Props = { className:string } function Button(props:Props){ const {className} = props return <button className={className}></button> } 说明:Button组件只能传入名称为className的prop参数,类型为string, 且为必填
讯享网 为children添加类型 children是一个比较特殊的prop, 支持多种不同类型数据的传入,需要通过一个内置的ReactNode类型来做注解 type Props = { className:string, children:React.ReactNode } function Button(props:Props){ const {className,children} = props return <button className={className}>{children}</button> } 说明:注解之后,children可以是多种类型,包括:React.ReactElement 、string、number、 React.ReactFragment 、React.ReactPortal 、boolean、 null 、undefined
为事件prop添加类型 组件经常执行类型为函数的prop实现子传父,这类prop重点在于函数参数类型的注解 type Props = { onGetMsg?:(msg:string)=>void } function Son(props:Props){ const {onGetMsg} = props const clickHandler = ()=>{ onGetMsg?.(‘this is msg’) } return <button onClick={clickHandler}>sendMsg</button> } 父组件 return( 讯享网<> <Son onGetMsg={(msg)=>console.log(msg)} /> </>
) 父组件 const getMsgHandler = (msg:string)=>{ console.log(msg)
} return( <> 讯享网<Son onGetMsg={getMsgHandler}/>
</> ) 说明:
- 在组件内部调用时需要遵守类型的约束,参数传递需要满足要求
- 绑定prop时如果绑定内联函数直接可以推断出参数类型,否则需要单独注解匹配的参数类型
useRef与TS
获取dom 获取dom的场景,可以直接把要获取的dom元素的类型当成泛型参数传递给useRef,可以推导出.current属性的类型 function App(){ const domRef = useRef<HTMLInputElement>(null) useEffect(()=>{ domRef.current?.focus() },[]) return( <> <input ref={domRef}/> </> ) }
讯享网引用稳定的存储器 把useRef当成引用稳定的存储器使用的场景可以通过泛型传入联合类型来做,比如定时器的场景 function App(){ const timerRef = useRef<number | undefined>(undefined) useEffect(()=>{ timerRef.current = setInterval(()=>{ console.log(‘1’) },1000) return ()=> clearInterval(timerRef.current) },[]) return <>this is div</> }



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/186440.html