react学习
目录
一、react基础
- jsx
大括号的作用
{count}
{userLlist.map((item)=>{return <li key={item.id}>{item.name}</li>}) }
key是用于react内部渲染处理的
- 基础条件渲染
{flag && <p>{"显示"}</p>}
- 复杂条件渲染
function getItem(){
if(type==1) return <p>有图模式<p/>
else if(type==2) return <>无图</>
}
2、useState使用
state是状态变量,数据变化视图变化
const [userList,setUserList]=useState([{id:1,name:"z"}])
3.map,filter函数使用
4.tab切换功能实现
const tab={{type:" ",text:" "}}
//将type设为class高亮
5.loadsh使用排序
import * as _ from 'lodash'
setCommentList(_.orderby(commentList,'star'//字段名,'desc'))
//不改变原数组
6.classnames优化类名控制
7.受控绑定表单
<input
value={value}
onChange={(e)=>{
setValue(e.target.value); //显示输入
}}
type='text'
/>
8.ref获取DOM对象
const inputRef=useRef(null);
<input ref={inputRef}/>
//使用inputRef.current获取DOM对象
9.uuid和dayjs库的使用
10.props使用
用于父传子组件消息
function Son(prop){
prop.name
prop.children //特殊属性
}
function Father(prop){
return <Son name="xxx"><p>this is span<p/></Son>
}
11.子传父,兄弟之间传消息(利用子传父,父传兄弟)
12.使用Context跨层通信
1、全局中createContext创建一个Context上下文对象
2、上层用<Context.Provider value={mdg}></>传递数据
3、底层用useContext(Context)方法获取数据
*13.UseEffect
const [commentList,setCommentList]=useState([])
useEffect(()=>{
async function getCommentList(){
// async异步,await等待
const res=await fetch('/comment').then(res=>res.json().then(data=>{console.log(data);return data}))
setCommentList(res);
}
getCommentList()
},[])
清除副作用,最常见是在组件卸载时候
14.自定义hook
- 构造一个use开头的函数名
- 在函数体内封装可复用的逻辑
- 把组件中用到的状态变量return出去
- 使用时解构出来
15.hook使用规则
1.组件外使用 x
2.if,for循环内使用 x
16.json-server和axios使用
17. UseMemo
- 对于计算数据量大的函数,当重新渲染时,函数结果不必重新执行,用于性能优化
当点击button2时,组件重新渲染,但result不会重新计算,只有点击button1时才会重新计算 - memo:将 memo(function APP1(){}),当子组件prop无变化时,使用memo可以阻止子组件渲染。
prop的比较机制:使用Object.is,基础类型和引用类型不同
[]!==[]因为是不同的对象实例
useCallback
useCallback
是React的一个Hook,用于优化性能,它可以帮助我们避免在渲染过程中不必要地创建新的函数实例。
它接受两个参数:一个是我们需要记忆化的函数,另一个是一个依赖项数组。当依赖项发生变化时,useCallback
会返回一个新的记忆化函数。
useCallback
的主要用途是优化性能。在React中,如果我们在组件渲染时创建函数,那么每次渲染都会创建一个新的函数实例。如果这个函数被用作子组件的props,那么即使父组件的状态或props没有变化,子组件也会因为接收到新的函数实例而重新渲染。通过使用useCallback
,我们可以确保在依赖项没有变化的情况下,始终使用同一个函数实例,从而避免不必要的子组件重新渲染。
例如,以下代码创建了一个记忆化的`handleClick`函数,只有当`id`发生变化时,才会创建新的函数实例:
const handleClick = useCallback(() => {
console.log(id);
}, [id]);
return <button onClick={handleClick}>Click me</button>;
下例中,与memo配合使子组件不重复渲染(**因为还使用上一个函数实例子组件的prop参数未发生变化)**,性能优化
useRequest
useRequest是ahook第三方库中提供的一个hook
在获取数据方面,可以代替useEffect
const { data, error, loading, run } = useRequest(fetchData);
// 在需要的时候调用 run 函数来触发数据请求
const handleFetchData = () => {
run();
};
USeRequest返回五个参数,可通过解构赋值获取
- data: 保存请求成功时的数据。
- error: 保存请求失败时的错误信息。
- loading: 表示当前请求是否正在加载中。
- cancel: 用于取消当前请求的函数。
- run: 触发请求的函数。
二、 react使用redux
在我们继续之前,你需要熟悉一些重要的 Redux 术语:
- state
- action,action 是一个具有 type 字段的普通 JavaScript 对象,只描述发生了什么事情,有type,payload字段
- reducer是一个纯函数,接收当前的 state 和一个 action 对象,必要时决定如何更新状态,并返回新状态。函数签名是:(state, action) => newState。 你可以将 reducer 视为一个事件监听器,它根据接收到的 action(事件)类型处理事件。
- dispatch,调用action
- UseSelector:允许你从 Redux store 中选择状态并订阅其更改,代替了connect
三、美团外卖项目
- 添加按钮怎么显示?
解决方法:antd icon
- 滚动菜单如何实现
解决方法:将延长的区域设置overflow:auto - flex
flex:1 不管内容多少,一般都是平分空间,空间大小都一致、
而 flex:auto 是根据内容的大小来分,不是平的(除非内容都是一样,才平分)
完成页面制作
使用redux渲染页面
完成购物车功能
store.js
// 编写store
import { createSlice } from "@reduxjs/toolkit"
import axios from "axios"
const foodsStore = createSlice({
name: 'foods',
initialState: {
// 商品列表
foodsList: [],
// 菜单激活下标值
activeIndex: 0,
// 购物车列表
cartList: []
},
reducers: {
// 更改商品列表
setFoodsList (state, action) {
// payload是传入的值
state.foodsList = action.payload
},
changeActiveIndex(state,action){
state.activeIndex = action.payload
},
addCart (state, action) {
// 是否添加过?以action.payload.id去cartList中匹配 匹配到了 添加过
const item = state.cartList.find(item => item.id === action.payload.id)
if (item) {
item.count++
} else {
state.cartList.push(action.payload)
}
},
// count增
increCount (state, action) {
// 关键点:找到当前要修改谁的count id
const item = state.cartList.find(item => item.id === action.payload.id)
item.count++
},
// count减
decreCount (state, action) {
// 关键点:找到当前要修改谁的count id
const item = state.cartList.find(item => item.id === action.payload.id)
if (item.count === 0) {
return
}
item.count--
},
clearCart(state){
state.cartList=[];
},
}
})
// 异步获取部分
const { setFoodsList, changeActiveIndex, addCart, increCount, decreCount, clearCart } = foodsStore.actions
const fetchFoodsList = () => {
return async (dispatch) => {
// 编写异步逻辑
const res = await axios.get('meituan/menu')
// 调用dispatch函数提交action
dispatch(setFoodsList(res.data))
}
}
export { fetchFoodsList, changeActiveIndex, addCart, increCount, decreCount, clearCart }
const reducer = foodsStore.reducer
export default reducer
使用react-router-dom
- 制作路由表
const router = createBrowserRouter([
{
path:"login",
element:<DempPage/>
},
{
path:"index",
element:<DempPage/>
}
])
- 声明式导航
<Link to='/index' />
- 编程式导航
useNavigate()
- Routes 多个Route需要Route包起来
- Route
- Outle 给children占位
request请求中的url(‘xxx’)都是基于当前上级路由url的拼接,是相对路由
url(‘/xxx’)是绝对路由,根。
重定向默认路由
const router = createBrowserRouter(
[
{
path:"/",
element:<App/>,
children:
[
{
path:"/",
// replace属性表示这是一个替换操作,而不是在历史记录中添加新的条目。
element: <Navigate to="/home" replace />
},
{
path:"home",
element:<Home/>,
}
}
]
查看评价
在img标签里面只设置宽度,不设置高度,图片就会等比例缩放。
封装request请求
import axios from "axios";
const api= axios.create({
baseURL:"http://geek.itheima.net/v1_0",
timeout:5000
})
// 请求拦截
api.interceptors.request.use((config)=>{
return config
},(error)=>{
return Promise.reject(error);
})
// 响应拦截
api.interceptors.response.use((response)=>{
return response.data;
},(error)=>{
return Promise.reject(error);
})
interface Request {
get: (url: string) => Promise<any>;
post: (url: string, params: any) => Promise<any>;
}
// 封装request模块
const request: Request = {
get: (url: string) => api.get(url),
post: (url: string, params: any) => api.post(url, { ...params })
};
// const request = (method, url, data = null) => {
// return api({
// method: method,
// url: url,
// data: data,
// // 其他请求配置
// })
// .then(response => {
// // 处理请求成功的响应
// return response.data;
// })
// .catch(error => {
// // 处理请求失败的情况
// console.error('Request failed:', error);
// throw error;
// });
//};
export default request;
Token管理
- redux管理token
- 使用localstorag存储token,实现持久化管理