路由基本使用

  • 安装插件 npm install react-router-dom
  • /src/index.js ```jsx import React from ‘react’; import ReactDOM from ‘react-dom’; import App from ‘./App’; import {HashRouter} from ‘react-router-dom’

/**

  • HashRouter 开启路由 */ ReactDOM.render( , document.getElementById(‘root’) );
  1. - src/components/home.js
  2. ```jsx
  3. import React, { Component } from 'react'
  4. class Home extends Component {
  5. render() {
  6. return (
  7. <div>Home 首页内容</div>
  8. )
  9. }
  10. }
  11. export default Home
  • src/components/list.js ```jsx import React, { Component } from ‘react’

class List extends Component { render() { return (

List 列表页内容
) } }

export default List

  1. - src/App.js
  2. ```jsx
  3. import React, {Component} from 'react'
  4. import {Link, Route} from 'react-router-dom'
  5. import Home from './components/home'
  6. import List from './components/list'
  7. /**
  8. * Link: to 属性指定跳转的链接
  9. * Router: path component
  10. */
  11. class App extends Component {
  12. render() {
  13. return (
  14. <div>
  15. <div>
  16. <Link to='/home'>首页</Link>----
  17. <Link to='/list'>列表页</Link>
  18. </div>
  19. <hr />
  20. <div>
  21. <Route path='/home' component={Home} />
  22. <Route path='/list' component={List} />
  23. </div>
  24. </div>
  25. )
  26. }
  27. }
  28. export default App

exact 属性-默认展示内容

  • src/App.js
    1. <div>
    2. <Route path="/" component={Home} exact />
    3. <Route path='/home' component={Home} />
    4. <Route path='/list' component={List} />
    5. </div>

路由匹配规则

  • src/App.js ```jsx import React, {Component} from ‘react’ import {Link, Route, Switch} from ‘react-router-dom’ import Home from ‘./components/home’ import List from ‘./components/list’ import NotFound from ‘./components/notFound’

/**

  • Link: to 属性指定跳转的链接
  • Router: path component */

class App extends Component { render() { return (

首页—— 列表页

) } }

export default App

  1. <a name="kWUVs"></a>
  2. ## 动态路由传参
  3. - 路由参数占位符 src/App.js
  4. ```jsx
  5. import Detail from './components/detail'
  6. class App extends Component {
  7. render() {
  8. return (
  9. <div>
  10. <div>
  11. <Link to='/home'>首页</Link>----
  12. <Link to='/list'>列表页</Link>
  13. </div>
  14. <hr />
  15. <div>
  16. <Switch>
  17. <Route path="/" component={Home} exact />
  18. <Route path='/home' component={Home} />
  19. <Route path='/list' component={List} exact />
  20. <Route path="/detail/:id" component={Detail} />
  21. <Route component={NotFound} />
  22. </Switch>
  23. </div>
  24. </div>
  25. )
  26. }
  27. }
  28. export default App
  • 触发操作的时候传递具体的参数 src/components/list.js ```jsx import React, { Component } from ‘react’ import { Link } from ‘react-router-dom’

class List extends Component { render() { return (

测试文章1

测试文章2

) } }

export default List

  1. - 在具体的组件当中使用传递的参数 src/components/detail.js
  2. ```jsx
  3. import React, { Component } from 'react'
  4. class Detail extends Component {
  5. render(props) {
  6. console.log(this.props.match.params.id)
  7. return (
  8. <div>{this.props.match.params.id}</div>
  9. )
  10. }
  11. }
  12. export default Detail

查询参数传参

  • src/components/list ```jsx import React, { Component } from ‘react’ import { Link } from ‘react-router-dom’

class List extends Component { render() { return (

测试文章1

测试文章2

测试文章3

) } }

export default List

  1. - src/components/home.js
  2. ```jsx
  3. import React, { Component } from 'react'
  4. import qs from 'qs'
  5. class Home extends Component {
  6. render(props) {
  7. // console.log(this.props.location.search)
  8. console.log(qs.parse(this.props.location.search, {ignoreQueryPrefix: true}))
  9. let param = qs.parse(this.props.location.search, {ignoreQueryPrefix: true})
  10. return (
  11. <div>Home 首页内容 {param.title}</div>
  12. )
  13. }
  14. }
  15. export default Home

嵌套路由

  • src/components/list.js ```jsx import React, { Component } from ‘react’ import { Link, Route} from ‘react-router-dom’ import Outer from ‘../components/outer’ import Inner from ‘../components/inner’

class List extends Component { render(props) { console.log(this.props) return (

测试文章1

测试文章2

测试文章3

国内新闻 国际新闻
) } }

export default List

  1. <a name="jfxqN"></a>
  2. ## 路由跳转及重定向
  3. - src.components/home.js
  4. ```jsx
  5. import { Redirect } from 'react-router-dom'
  6. class Home extends Component {
  7. render(props) {
  8. const isLogin = false
  9. if (!isLogin) {
  10. return <Redirect to="/list" />
  11. }
  12. let param = qs.parse(this.props.location.search, {ignoreQueryPrefix: true})
  13. return (
  14. <div>Home 首页内容 {param.title}</div>
  15. )
  16. }
  17. }
  18. export default Home

路由守卫

  • src/auth.js ```javascript class Authorized { constructor() { this.authorized = false }

    login() { this.authorized = true }

    logout() { this.authorized = false }

    isAuthorized() { return this.authorized } }

export default new Authorized()

  1. - src/App.js
  2. ```jsx
  3. import auth from './auth'
  4. class App extends Component {
  5. render() {
  6. return (
  7. <div>
  8. <div>
  9. <Link to='/home'>首页</Link>----
  10. <Link to='/list'>列表页</Link>
  11. </div>
  12. <hr />
  13. <div>
  14. <Switch>
  15. <Route path="/" component={Home} exact />
  16. <Route path='/home' component={Home} />
  17. {/* <Route path='/list' component={List} /> */}
  18. <Route path='/list' render={props => {
  19. if (auth.isAuthorized()) {
  20. // 进入路由
  21. return <List {...props} />
  22. }else {
  23. // 重定向
  24. return <Redirect to='/home' />
  25. }
  26. }} />
  27. <Route path="/detail/:id" component={Detail} />
  28. <Route component={NotFound} />
  29. </Switch>
  30. </div>
  31. </div>
  32. )
  33. }
  34. }
  35. export default App
  • src/components/home.js ```jsx import React, { Component } from ‘react’ import qs from ‘qs’ import auth from ‘../auth’ class Home extends Component { login = () => { // 执行登陆 auth.login() alert(‘登陆成功’) } render(props) {

    let param = qs.parse(this.props.location.search, {ignoreQueryPrefix: true}) return (

    1. <div>
    2. <p>Home 首页内容 {param.title}</p>
    3. <button onClick={this.login}>登陆</button>
    4. </div>

    ) } }

export default Home

  1. - src/components/list.js
  2. ```jsx
  3. import { createHashHistory } from 'history'
  4. class List extends Component {
  5. logout = () => {
  6. auth.logout()
  7. createHashHistory().push('/home')
  8. }
  9. render() {
  10. console.log(this.props)
  11. return (
  12. <div>
  13. <div>
  14. <button onClick={this.logout}>退出登录</button>
  15. </div>
  16. </div>
  17. )
  18. }
  19. }
  20. export default List

路由守卫组件

  • src/guard.js ```jsx import React,{ Component } from ‘react’ import { Redirect, Route} from ‘react-router’ import auth from ‘./auth’

class AuthRouteGuard extends Component { render () { const {component: Component, …rest} = this.props return ( { if(auth.isAuthorized()) { return } else { return } }} /> ) } }

export default AuthRouteGuard

  1. - src/App.js
  2. ```jsx
  3. <Switch>
  4. <Route path="/" component={Home} exact />
  5. <Route path='/home' component={Home} />
  6. <AuthRouteGuard path='/list' component={List} />
  7. <Route path="/detail/:id" component={Detail} />
  8. <Route component={NotFound} />
  9. </Switch>

路由模块懒加载

  • 安装插件 npm install @loadable/component
  • src/App.js ```jsx import loadComponent from ‘@loadable/component’

const Home = loadComponent(() => import(‘./components/home’)) const List = loadComponent(() => import(‘./components/list’)) const NotFound = loadComponent(() => import(‘./components/notFound’)) const Detail = loadComponent(() => import(‘./components/detail’))

  1. <a name="P4Xk2"></a>
  2. ## 非路由组件传递路由信息
  3. - src/components/test.js
  4. ```jsx
  5. import React, { Component } from 'react'
  6. import { withRouter } from 'react-router-dom'
  7. class Test extends Component {
  8. render() {
  9. console.log(this.props)
  10. return (
  11. <div>
  12. Test组件
  13. </div>
  14. )
  15. }
  16. }
  17. export default withRouter(Test)
  • src/components/detail.js ```jsx

import Test from ‘./test’ class Detail extends Component { render(props) { return (

{this.props.match.params.id}

) } }

export default Detail

  1. <a name="VRazC"></a>
  2. ##
  3. <a name="sK1IB"></a>
  4. ## useState 设置状态
  5. - 什么是 HOOK
  6. - 它是一个特殊的函数
  7. - 可以让函数组件也具有类组件的特性
  8. - 为什么需要 HOOK
  9. - 数据共享
  10. - 多个业务逻辑代码有可能会存在于同一个生命周期函数中
  11. - useState
  12. - 一个可以在函数组件中保存状态的 HOOK 函数
  13. - 参数: 保存状态的初始值
  14. - 返回值
  15. - 一个数组
  16. - 第一个元素就是当前保存的状态
  17. - 第二个就是修改当前保存状态的方法
  18. - src/App.js
  19. ```jsx
  20. import React, { useState } from 'react'
  21. function App() {
  22. const arr = useState(0)
  23. const [state, setState] = arr
  24. console.log(state, setState)
  25. return (
  26. <div>
  27. 数据: {state}
  28. <button onClick={() => { setState(state + 1) }}>+1</button>
  29. <button onClick={() => { setState(state - 1) }}>-1</button>
  30. </div>
  31. )
  32. }
  33. export default App

注意点

  • 在函数组件中可以多次使用同一个 HOOK 函数
  • 简单类型 复杂
  • set操作也是异步的,不能直接修改 state 的元素值 ```jsx import React, { useState } from ‘react’

function App() {

const [ageState, setAgeState] = useState(10) const [nameState, setNameState] = useState(‘zz’) const [personState, setPersonState] = useState({“name”: “jj”, “age”: 20})

const [listState, setListState] = useState([ {name: ‘zoe’, age: 18}, {name: ‘zce’, age: 30}, {name: ‘zzz’, age: 25} ])

// 定义修改第一个 age 值的方法 function incrementAge() { // setAgeState(ageState + 10) // setAgeState(ageState + 10) // setAgeState(ageState + 10) setAgeState((pre) => pre + 10) setAgeState((pre) => pre + 10) setAgeState((pre) => pre + 10) } // 定义修改第二个人物状态 name 的操作 function changeName() { // personState.name = ‘拉钩教育’ setPersonState({…personState, name: ‘拉钩教育’}) } return (

数据: {ageState}—- {nameState}
数据:{personState.name}—-{personState.age}
{ listState.map(item => { return (

{item.name}—-{item.age}

) }) }
) } export default App

  1. <a name="AnHjy"></a>
  2. ## useEffect 使用
  3. ```jsx
  4. import React, { useState, useEffect} from 'react'
  5. /**
  6. * useEffect
  7. * 挂载 更新 卸载
  8. */
  9. function Header() {
  10. const [strState, setStrState] = useState('拉钩教育')
  11. const [numState, setNumState] = useState(10)
  12. useEffect(() => {
  13. console.log('挂载与更新操作完成了')
  14. return () => {
  15. console.log('卸载的时候执行')
  16. }
  17. }, [strState])
  18. return (
  19. <div>
  20. <p>{strState} <button onClick={() => {setStrState('大前端')}}>修改字符</button></p>
  21. <p>{numState} <button onClick={() => {setNumState(numState + 1)}}>修改数值</button></p>
  22. </div>
  23. )
  24. }
  25. function App() {
  26. const [isShow, setIsShow] = useState(true)
  27. return (
  28. <div>
  29. {isShow && <Header />}
  30. <hr />
  31. <button onClick={() => { setIsShow(!isShow) }}>切换</button>
  32. </div>
  33. )
  34. }
  35. export default App

优点

  1. import React, { useState, useEffect} from 'react'
  2. /**
  3. * useEffect
  4. * 挂载 更新 卸载
  5. */
  6. function Header() {
  7. const [strState, setStrState] = useState('拉钩教育')
  8. const [numState, setNumState] = useState(10)
  9. useEffect(() => {
  10. // 事件监听添加操作
  11. console.log('事件监听添加操作')
  12. return () => {
  13. console.log('事件移除监听')
  14. }
  15. })
  16. useEffect(() => {
  17. // '发送网络请求获取数据'
  18. console.log('发送网络请求获取数据')
  19. })
  20. useEffect(() => {
  21. // 判断是否登录
  22. console.log('判断是否登录')
  23. })
  24. useEffect(() => {
  25. console.log('挂载与更新操作完成了')
  26. return () => {
  27. console.log('卸载的时候执行')
  28. }
  29. }, [strState])
  30. return (
  31. <div>
  32. <p>{strState} <button onClick={() => {setStrState('大前端')}}>修改字符</button></p>
  33. <p>{numState} <button onClick={() => {setNumState(numState + 1)}}>修改数值</button></p>
  34. </div>
  35. )
  36. }
  37. function App() {
  38. const [isShow, setIsShow] = useState(true)
  39. return (
  40. <div>
  41. {isShow && <Header />}
  42. <hr />
  43. <button onClick={() => { setIsShow(!isShow) }}>切换</button>
  44. </div>
  45. )
  46. }
  47. export default App

useContext

  1. import React, { createContext, useContext } from 'react'
  2. const UserContext = createContext({})
  3. const AreaContext = createContext({})
  4. // 定义 Header 组件
  5. function Header() {
  6. const userInfo = useContext(UserContext)
  7. const areaInfo = useContext(AreaContext)
  8. return (
  9. <div>
  10. <p>{userInfo.name}</p>
  11. <p>{userInfo.age}</p>
  12. <p>{areaInfo.width}</p>
  13. </div>
  14. )
  15. }
  16. function App() {
  17. return (
  18. <div>
  19. <UserContext.Provider value={{ "name": "syy", "age": 18 }}>
  20. <AreaContext.Provider value={{ "width": 200 }}>
  21. <Header />
  22. </AreaContext.Provider>
  23. </UserContext.Provider>
  24. </div>
  25. )
  26. }
  27. export default App

useReducer

  1. import React, { useReducer } from 'react'
  2. function reducer(state, action) {
  3. switch (action.type) {
  4. case 'add':
  5. return { ...state, num: state.num + 1 }
  6. case 'sub':
  7. return { ...state, num: state.num - 1 }
  8. default:
  9. return { ...state }
  10. }
  11. }
  12. // Home
  13. function Home() {
  14. const [state, dispatch] = useReducer(reducer, { num: 0 })
  15. return (
  16. <div>
  17. <p>数据: {state.num}</p>
  18. <button onClick={() => { dispatch({ type: "add" }) }}>+ 1</button>
  19. <button onClick={() => { dispatch({ type: "sub" }) }}> - 1</button>
  20. </div>
  21. )
  22. }
  23. // About
  24. function About() {
  25. const [state, dispatch] = useReducer(reducer, { num: 10 })
  26. return (
  27. <div>
  28. <p>数据: {state.num}</p>
  29. <button onClick={() => { dispatch({ type: "add" }) }}>+ 1</button>
  30. <button onClick={() => { dispatch({ type: "sub" }) }}> - 1</button>
  31. </div>
  32. )
  33. }
  34. function App() {
  35. return (
  36. <div>
  37. <Home />
  38. <About />
  39. </div>
  40. )
  41. }
  42. export default App

useCallback

  1. import React, { useState, memo, useCallback} from 'react'
  2. // Home
  3. function Home(props) {
  4. console.log('Home组件被渲染了')
  5. return (
  6. <div>
  7. <p>Home组件</p>
  8. <button onClick={() => { props.handler() }}>减小</button>
  9. </div>
  10. )
  11. }
  12. // About
  13. function About(props) {
  14. console.log('About组件被渲染了')
  15. return (
  16. <div>
  17. <p>About组件</p>
  18. <button onClick={() => { props.handler() }}>增加</button>
  19. </div>
  20. )
  21. }
  22. const MemoHome = memo(Home)
  23. const MemoAbout = memo(About)
  24. function App() {
  25. console.log('App组件被渲染了')
  26. const [numState, setNumState] = useState(10)
  27. const [ageState, setAgeState] = useState(20)
  28. function increment() {
  29. setNumState(numState + 2)
  30. }
  31. // function decrement() {
  32. // setAgeState(ageState - 4)
  33. // }
  34. //
  35. const decrement = useCallback(() => {
  36. setAgeState(ageState - 4)
  37. }, [ageState])
  38. return (
  39. <div>
  40. <p>num数据: {numState}</p>
  41. <p>age数据: {ageState}</p>
  42. <hr />
  43. <MemoHome handler={decrement} />
  44. <hr />
  45. <MemoAbout handler={increment} />
  46. </div>
  47. )
  48. }
  49. export default App

useMemo

  1. import React, { useState, useMemo } from 'react'
  2. function getData() {
  3. console.log('getData被调用了')
  4. let data = 0
  5. for (let i = 0; i < 999; i++) {
  6. data += i
  7. }
  8. return data
  9. }
  10. function App() {
  11. console.log('App组件被渲染了')
  12. const [numState, setNumState] = useState(10)
  13. const [ageState, setAgeState] = useState(20)
  14. const num = useMemo(() => {
  15. return getData()
  16. }, [])
  17. function increment() {
  18. setNumState(numState + 10)
  19. }
  20. return (
  21. <div>
  22. <p>num数据: {numState}</p>
  23. <p>age数据: {ageState}</p>
  24. <button onClick={() => { increment() }}>修改</button>
  25. <p>{num}</p>
  26. </div>
  27. )
  28. }
  29. export default App

useRef

  1. import React, { useState, useRef } from 'react'
  2. /**
  3. * 01 useRef 可以用于获取元素
  4. * 02 useRef 还可以保存数据
  5. * 03 useRef 保存的数据除非我们手动修改,否则的话它是不会改变的
  6. */
  7. function App() {
  8. const [numState, setNumState] = useState(100)
  9. const obj = useRef(numState)
  10. return (
  11. <div>
  12. <p>obj当中的 current: {obj.current}</p>
  13. <p>{numState}</p>
  14. <button onClick={() => { setNumState(numState + 1) }}>操作</button>
  15. </div>
  16. )
  17. }
  18. export default App

useImperativeHandle

  1. import React, {useRef, forwardRef, useImperativeHandle } from 'react'
  2. function Home(props, oHome) {
  3. const oInput = useRef()
  4. useImperativeHandle(oHome, () => {
  5. return {
  6. setValue: () => {
  7. oInput.current.value = "Home自己实现的setValue方法"
  8. }
  9. }
  10. })
  11. return (
  12. <div>
  13. <h2>Home组件</h2>
  14. <input ref={oInput}></input>
  15. </div>
  16. )
  17. }
  18. const ForwardHome = forwardRef(Home)
  19. function App() {
  20. const oHome = useRef()
  21. function btnClick() {
  22. console.log(oHome)
  23. oHome.current.setValue()
  24. }
  25. return (
  26. <div>
  27. <ForwardHome ref={oHome} />
  28. <button onClick={() => { btnClick() }}>操作input</button>
  29. </div>
  30. )
  31. }
  32. export default App

useLayoutEffect

  1. import React, { useState, useRef, useEffect, useLayoutEffect } from 'react'
  2. import './App.css'
  3. function Home() {
  4. const oP = useRef()
  5. // useEffect(() => {
  6. // oP.current.style.left = '0px'
  7. // oP.current.style.left = '600px'
  8. // console.log('挂载|更新, useEffect')
  9. // return () => {
  10. // console.log('卸载, useEffect')
  11. // }
  12. // })
  13. // 先于 useEffect 发生
  14. useLayoutEffect(() => {
  15. oP.current.style.left = '0px'
  16. oP.current.style.left = '600px'
  17. console.log('挂载|更新, , useLayoutEffect')
  18. return () => {
  19. console.log('卸载, useLayoutEffect')
  20. }
  21. })
  22. return (
  23. <div>
  24. home组件
  25. <p ref={oP}>Home组件中的 P元素</p>
  26. </div>
  27. )
  28. }
  29. function App() {
  30. const [isShow, setIsShow] = useState(true)
  31. return (
  32. <div>
  33. {isShow && <Home />}
  34. <button onClick={() => { setIsShow(!isShow) }}> 切换</button>
  35. </div>
  36. )
  37. }
  38. export default App

自定义 Hooks

  1. import React, { useState, useEffect } from 'react'
  2. // 以 use 开头
  3. function useAddEventListener(cName) {
  4. useEffect(() => {
  5. console.log(cName, '组件挂载|更新添加事件监听')
  6. return () => {
  7. console.log(cName, '卸载时取消事件监听')
  8. }
  9. })
  10. }
  11. function Home() {
  12. useAddEventListener('Home---')
  13. return (
  14. <div>
  15. Home组件
  16. </div>
  17. )
  18. }
  19. function About() {
  20. useAddEventListener('About---')
  21. return (
  22. <div>
  23. About组件
  24. </div>
  25. )
  26. }
  27. function App() {
  28. const [isShow, setIsShow] = useState(true)
  29. return (
  30. <div>
  31. {isShow && <Home />}
  32. {isShow && <About />}
  33. <button onClick={() => { setIsShow(!isShow) }}>切换</button>
  34. </div>
  35. )
  36. }
  37. export default App