关于前端:React项目开发常用API

2次阅读

共计 4733 个字符,预计需要花费 12 分钟才能阅读完成。

记录一下 React 我的项目开发罕用 API,作为后续开发的参考。

路由配置

配置文件模式

// router/index.js
import React, {lazy, Suspense} from 'react'

// Suspense 配合 lazy 实现懒加载
const SuspenseComponent = Component => {
  return (
    <Suspense>
      <Component></Component>
    </Suspense>
  )
}

const routes = [
  {
    path: '/',
    element: SuspenseComponent(lazy(() => import('../pages/index/Index'))),
  },
  {
    path: '/login',
    element: SuspenseComponent(lazy(() => import('../pages/login/Login')))
  },
  {
    path: '/list/:b',
    element: SuspenseComponent(lazy(() => import('../pages/list/List')))
  },
  {
    path: '*',
    element: SuspenseComponent(lazy(() => import('../pages/notFound/NotFound'))),
  },
]

export default routes

标签模式

import {HashRouter, Routes, Route} from 'react-router-dom'
import Index from './pages/index/Index'
import Login from './pages/login/Login'
import NotFound from './pages/NotFound/NotFound'

<React.StrictMode>
  <HashRouter>
    <Routes>
      <Route path='/' element={<Index />}></Route>
      <Route path='/login' element={<Login />}></Route>
      <Route path='*' element={<NotFound />}></Route>
    </Routes>
  </HashRouter>
</React.StrictMode>

路由鉴权

import React, {Fragment} from 'react'
import {useRoutes, Navigate, useLocation} from 'react-router-dom'
import routes from './router'
import {getToken} from './utils/auth'

const Permission = () => {const token = getToken()
    const location = useLocation()
    // 没有 token,且不是拜访登录页,重定向到登录页
    const toLogin = !token && location.pathname !== '/login'

    function RenderRoutes() {return useRoutes(routes)
    }

    return (
        <Fragment>
            {toLogin ? <Navigate to="/login" replace /> : <RenderRoutes />}
        </Fragment>
    )
}

export default Permission

路由跳转,传参

标签跳转

import {Link} from 'react-router-dom'

<Link to={{pathname: '/'}}>
    <button> 跳转 </button>
</Link>

useNavigate 跳转

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

const navigate = useNavigate()

/** 
  * 三种路由传参形式
  * 1、申明传参:/list/:id
  * 2、地址栏传参: /list?id=1
  * 3、state 属性传参:state: {id: 1}
  */
navigate('/List/3?a=2', {state: { id: 1}
})

history 跳转(后退、后退)

// history.js
import {createHashHistory} from 'history'

export default createHashHistory()


import history from './history'

history.back()

款式编写

styled-components

// App.js
import {ThemeProvider} from 'styled-components'

// 传递主题
<ThemeProvider theme={{primaryColor: '#db3046'}}>
  <Permission />
</ThemeProvider>
// index/style.js
import styled from 'styled-components'

export default styled.div`
  height: 100vh;
  display: flex;
  flex-direction: column;
  .nav {
      height: 70px;
      padding: 0 20px;
      background-color: ${props => props.theme.primaryColor};
      display: flex;
      align-items: center;
      .title {
          text-align: left;
          flex: 1;
          font-size: 20px;
          font-weight: 600;
          color: yellow;
      }
  }
`

状态治理

创立模块

// store/features/user.js
import {createSlice, createAsyncThunk} from '@reduxjs/toolkit'
import {getToken, getUserInfo, removeToken, removeUserInfo} from '../../utils/auth'
import {logout} from '../../api/login'
import history from '../../lib/history'

export const logoutAction = createAsyncThunk('user/logout', async () => {return await logout()
})

const slice = createSlice({
  name: 'user',
  initialState: {token: getToken(),
    userInfo: getUserInfo(),},
  reducers: {setToken(state, { payload}) {state.token = payload},
    setUserInfo(state, { payload}) {state.userInfo = payload},
  },
  extraReducers(builder) {builder.addCase(logoutAction.fulfilled, (state, { payload}) => {if (payload.success && payload.code === 200) {
        state.token = ''state.userInfo =''
        removeToken()
        removeUserInfo()
        history.push('/login')
        location.reload()}
    })
  },
})

export const {setToken, setUserInfo} = slice.actions

export default slice.reducer

注册模块

// store/index.js
import {configureStore} from '@reduxjs/toolkit'
import userReducer from './features/user'

export default configureStore({
  reducer: {user: userReducer}
})

传递状态

import {Provider} from 'react-redux'
import store from './store/index'
import App from './App'

<Provider store={store}>
  <App />
</Provider>

获取、操作状态

import {useSelector, useDispatch} from 'react-redux'
import {logoutAction} from '../../store/features/user'

const {userInfo} = useSelector(store => store.user)
const dispatch = useDispatch()

return (
  <div>
    <div>{userInfo.realName}</div>
    <button onClick={() => dispatch(logoutAction())}> 登出 </button>
  </div>
)

函数组件应用钩子

import React, {useState, useEffect} from 'react'

function onRequest() {}

const [number, setNumber] = useState(0)

/**
 * useEffect 第二个参数不传,任意状态产生扭转,都会执行
 * 传 [],只在组件挂载后执行
 * 传 [number],在组件挂载后和 number 变动后执行
 */
useEffect(() => {onRequest()
}, [number])

代码优化

缩小反复渲染

memo

// 调用 memo,当父组件从新渲染,然而 props 不变时,子组件读取缓存
import React, {memo} from 'react'

const Child = () => {
  return (<div>child</div>)
}

export default memo(Child)

useCallback

// 应用 useCallback 处理函数,当父组件从新渲染,依赖数组不变时,返回雷同函数,防止触发 props 变动,导致子组件从新渲染
import React, {useState, useCallback} from 'react'
import Child from 'Child'

const Parent = () => {const [value, setValue] = useState(0)
  function sum() {setValue(value + 1)
  }

  const sumCall = useCallback(sum, [])
  return (
    <div>
      <div>{value}</div>
      <Child onClick={sumCall} />
    </div>
  )
}

缩小反复计算

useMemo

// 调用 useMemo,当组件从新渲染时,若依赖数组不变,间接读取缓存的后果
import React, {useMemo, useState} from 'react'

const Parent = () => {const [value, setValue] = useState(0)
  function sum() {
    let result = 0
    for(let i = 0; i < 100000; i++) {result++}

    return result
  }

  const result = useMemo(sum, [])
  return (
    <div>
      <div>{value + result}</div>
      <button onClick={() => setValue(value + 1)}></button>
    </div>
  )
}
正文完
 0