react 学习笔记(2)

reactRouter:

前端路由:一个路径path对应一个组件component当我们在浏览器中访问一个path时,path对应的组件会在页面中进行渲染

抽象路由模块:

路由跳转:

路由系统中的多个路由组件之间需要进行路由跳转,并且在跳转同时需要进行参数传递

通常给组件的to属性指定要跳转的路由path,组件会被渲染为浏览器支持的a链接,如果需要传参直接通过字符串拼接的方式拼接参数即可

Link:

编程式导航:

编程式是指通过'useNavigate'钩子得到的导航方法,然后通过调用方法以命令的方式进行路由跳转

语法说明:通过调用navigate方法传入地址实现跳转

import { useNavigate } from "react-router-dom"

const Login=()=>{
    const navigate=useNavigate()
    return <div>我是登录页
    <button onClick={()=>navigate('/article')}>跳转文章页</button>   
    <button onClick={()=>navigate('/article/1001')}>searchParams传参</button>           
    </div>
}
export default Login

导航传参:

获取参数:

useSearchParams返回的是一个数组

params传参:

useParams返回的是一个对象

import { useParams  } from "react-router-dom"

const Article=()=>{
    const params=useParams()
   let id=params.id
    return <div>我是文章,{id} </div>
}
export default Article

嵌套路由:

在一级路由中又嵌套了其他路就叫做嵌套路由

实现步骤:

  1. 使用children属性配置路由嵌套关系

  2. 使用<Outlet/>组件配置二级路由渲染位置+

import { Link, Outlet } from "react-router-dom"

const Layout=()=>{
    return <div>
          这是一级路由
          <Link to="/">面板</Link>
          <Link to="/about">关于</Link>
          {/*  配置二级路由的出口*/}
          <Outlet/>
    </div>
           
}
export default Layout

当访问的是一级路由时,默认的二级路由组件可以得到渲染,只需要在二级路由的位置去掉path,设置index属性为true

路由模式:

react提供两种路由模式:history模式和Hash模式,reactRouter分别由createBrowerRouter和createHashRouter函数创建

路由模式url表现底层原理是否需要后端只支持
historyurl/loginhistory对象+pushState对象需要
hashurl/#/login监听hashChange事件不需要

redux:

redux是react最常用的集中状态管理工具,可以独立于框架运行

react本质上是一个UI库,他是单项数据流的,数据只能从父组件通过props传给子组件,如果子组件想要修改父组件的值,只能通过绑定函数传递参数的形式来修改,数据比较复杂时,不好操作,所以需要redux协助

作用:通过集中管理的方式管理应用的状态

redux把整个数据的修改分成了三个核心概念,分别是:state、action、reducer

  1. state:一个对象 存放着我们管理的数据状态

  2. action:一个对象 用来描述你想怎样改数据

  3. reducer: 一个函数 根据action的描述生成一个新的state

在react组件中使用store中的数据,需要拥有一个钩子函数-useSelector,它的作用是把store中的数据映射到组件中

React组件中修改store中的数据需要借助另一个hook函数-useDispatch,它的作用是生成提交action对象的dispatch函数

action传参:

在reducers的同步修改方法中添加action对象参数,再调用actionCreater的时候传递参数,参数会被传递到action对象payload属性上

redux遵循的三个原则:

  1. 单一真实数据源。

  2. 状态是只读的

  3. 使用纯函数来进行修改

创建store

import { createSlice }  from '@reduxjs/toolkit'
import axios from 'axios'
 
 
const dataStore=createSlice({
    name:'data',
    initialState:{
         dataMoney:[]
    },
    reducers:{
        setBillData(state,actions){
            state.dataMoney=actions.payload
        }
        
})
 
const {setBillData,addBill}=dataStore.actions
let reducer=dataStore.reducer

redux异步操作:

  1. 创建store的写法保持不变,配置好同步修改状态的方法

  2. 单独封装一个函数,在函数内部return一个新函数,在新函数中

    3.组件中的dispatch写法保持不变

    1. 封装异步请求获取数据

    2. 调用同步actionCreater传入异步数据生成一个action对象,并使用dispatch提交

const fetchData=()=>{
    return async (dispatch)=>{
     const res=await axios.get('http://localhost:8888/ka')
    dispatch(setBillData(res.data))
     
    }
}

获取数据:

 const dataMoney=useSelector(state=>state.money.dataMoney)//获取数据
 useEffect(()=>{
      dispatch(fetchData())
    },[dispatch])

useMemo():

useMemo是react的一个重要的性能优化工具,可以避免在渲染过程中的不必要计算,从而提高组件性能

第一个参数是一个函数,用于进行计算,第二个参数是一个依赖数组,当依赖发生变化时会重新进行计算,useMemo会在每次渲染都计算新的值

import { useMemo } from "react";
import { useState } from "react";

// 消耗非常大的计算才用useMemo
 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(()=>{
    console.log('组建重新渲染');   
    return fib(count1)
      
    },[count1])
    
    const [count2,setCount2]=useState(0)
    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;

useReducer:

和useState的作用类似,用来管理相对复杂的状态数据

import { useReducer } from "react"

 //定义reduce函数,根据不同的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
    }
}

 //在组件中调用useReducer(reducer,0)=>[state,dispatch]

 //调用dispatch({type:'INC})
   
  function App() {
    const [state,dispatch]=useReducer(reducer,0)
    return(
        <div className="App">
         this is App
         
       <button onClick={()=>dispatch({type:'INC'})}>+</button>
        {state}
       <button onClick={()=>dispatch({type:'DEC'})}>-</button>
       <button onClick={()=>dispatch({type:'SET',payload:100})}>update</button>
       </div>
  
   
    )
       
    }
   export default App;

参数:

reducer:用于更新state的纯函数、。参数为state和action,返回值是更新后state

initialArg:用于初始state的任意值。初始值的计算逻辑取决于接下来的init参数

可选参数:用于计算函数的初始值,如果存在使用init(initialArg)的执行结果作为初始值。否则使用initialArg

返回值:返回一个有两个之组成的数组

dispatch返回的dispatch函数允许你更新state并触发组件的重新渲染

react.memo:

作用:允许组件在Props没有改变的情况下跳过渲染

React组件默认渲染机制:只要父组件重新渲染子组件就会重新渲染

经过memo函数包裹生成的缓存组件只有在props发生变化时才会重新渲染

 import { useMemo } from "react";
import { useState } from "react";
import { memo } from "react";

//传递一个简单类型的porp

//传递一个引用类型 当父组件的函数重新执行时,实际上形成的是新的数组引用
 const MemoComponent=memo(function Son(){
    console.log('我是子组件,我要重新渲染' );
    return <div>this is son </div>
 })

 function App() {
     const list=useMemo(()=>{
        return [1,2,3]
     },[]) 
    const [count,setCount]=useState(0)
    return (
      <div className="App">
        this is App
       <MemoComponent list={list} />
       <button onClick={()=>setCount(count+1)}>+</button>
             {count}
      </div>
    );
  }
  
  export default App;

react.memo-props的比较机制

机制:在使用memo缓存组件后,React会对每一个prop使用Object.js比较新值和老值,返回true,表示没有变化

prop是简单类型

Object.is(3,3)没有变化

prop是引用类型(对象/数组)

Object([],[])=>false 有变化,react只关心引用是否变化

当时用引用类型时:利用useMemo()组件渲染缓存的过程中缓存一个值

  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值