• [尚硅谷React笔记]——第8章 扩展


    目录:

    1. 扩展1_setState
    2. 扩展2_lazyLoad
    3. 扩展3_stateHook
    4. 扩展4_EffectHook
    5. 扩展5_RefHook
    6. 扩展6_Fragment
    7. 扩展7_Context
    8. 扩展8_PureComponent
    9. 扩展9_renderProps
    10. 扩展10_ErrorBoundary
    11. 组件通信方式总结

    1.扩展1_setState

    setState更新状态的2种写法

    • setState(stateChange, [callback])------对象式的setState
      • 1.stateChange为状态改变对象(该对象可以体现出状态的更改)
      • 2.callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
    • setState(updater, [callback])------函数式的setState
      • 1.updater为返回stateChange对象的函数。
      • 2.updater可以接收到state和props。
      • 3.callback是可选的回调函数, 它在状态更新、界面也更新后(render调用后)才被调用。
    • 总结:
    • 1.对象式的setState是函数式的setState的简写方式(语法糖)
    • 2.使用原则:
      • (1).如果新状态不依赖于原状态 ===> 使用对象方式
      • (2).如果新状态依赖于原状态 ===> 使用函数方式
      • (3).如果需要在setState()执行后获取最新的状态数据, 
      • 要在第二个callback函数中读取

    Demo.jsx

    1. import React, {Component} from 'react';
    2. class Demo extends Component {
    3. state = {count: 0}
    4. add = () => {
    5. //对象式的setState
    6. // const {count} = this.state
    7. // this.setState({count: count + 1}, () => {
    8. // console.log(this.state.count)
    9. // })
    10. // // console.log('12行的输出', this.state.count)
    11. //函数式的setState
    12. // this.setState((state, props) => {
    13. // console.log(state, props)
    14. // return {count: state.count + 1}
    15. // })
    16. this.setState(state => ({count: state.count + 1}), () => {
    17. console.log(this.state.count)
    18. })
    19. // this.setState({count: this.state.count + 1})
    20. }
    21. render() {
    22. return (
    23. 当前求和为:{this.state.count}

  • );
  • }
  • }
  • export default Demo;
  • 2.扩展2_lazyLoad

    路由组件的lazyLoad

    1. //1.通过React的lazy函数配合import()函数动态加载路由组件 ===> 路由组件代码会被分开打包
    2. const Login = lazy(()=>import('@/pages/Login'))
    3. //2.通过指定在加载得到路由打包文件前显示一个自定义loading界面
    4. loading.....}>
    5. "/xxx" component={Xxxx}/>
    6. "/login"/>

    About.jsx

    1. import React, {Component} from 'react';
    2. class About extends Component {
    3. render() {
    4. return (
    5. 我是About的内容

  • );
  • }
  • }
  • export default About;
  • Demo.jsx

    1. import React, {Component, lazy, Suspense} from 'react';
    2. import {NavLink, Route} from "react-router-dom";
    3. import Loading from "../Loading/Loading";
    4. const Home = lazy(() => import('../Home/Home'))
    5. const About = lazy(() => import('../About/About'))
    6. class Demo extends Component {
    7. render() {
    8. return (
    9. "row">
    10. "col-xs-offset-2 col-xs-8">
    11. "page-header">

      React Router Demo

  • "row">
  • "col-xs-2 col-xs-offset-2">
  • "list-group">
  • "list-group-item" to="/about">About
  • "list-group-item" to="/home">Home
  • "col-xs-6">
  • "panel">
  • "panel-body">
  • }>
  • "/about" component={About}>
  • "/home" component={Home}>
  • );
  • }
  • }
  • export default Demo;
  • Home.jsx

    1. import React, {Component} from 'react';
    2. class Home extends Component {
    3. render() {
    4. return (
    5. 我是Home的内容

    6. );
    7. }
    8. }
    9. export default Home;

    Loading.jsx

    1. import React, {Component} from 'react';
    2. class Loading extends Component {
    3. render() {
    4. return (
    5. 'gray', color: 'orange'}}>Loading

    6. );
    7. }
    8. }
    9. export default Loading;

    App.js

    1. import React, {Component} from 'react';
    2. import Demo from "./components/Demo/Demo";
    3. class App extends Component {
    4. render() {
    5. return (
    6. );
    7. }
    8. }
    9. export default App;

    index.js

    1. import React from 'react';
    2. import ReactDOM from 'react-dom/client';
    3. import App from './App';
    4. import {BrowserRouter} from "react-router-dom";
    5. const root = ReactDOM.createRoot(document.getElementById('root'));
    6. root.render(
    7. );

    3.扩展3_stateHook

     React Hook/Hooks是什么?

    三个常用的Hook

    State Hook

     Demo.jsx

    1. import React, {Component} from 'react';
    2. // class Demo extends Component {
    3. // state = {count: 0}
    4. //
    5. // add = () => {
    6. // this.setState(state => ({count: state.count + 1}))
    7. // }
    8. //
    9. // render() {
    10. // return (
    11. //
    12. //

      当前求和为{this.state.count}

    13. //
    14. //
    15. // );
    16. // }
    17. // }
    18. function Demo() {
    19. const [count, setCount] = React.useState(0)
    20. const [name, setName] = React.useState('tom')
    21. function add() {
    22. // setCount(count + 1)
    23. setCount((count) => {
    24. return count + 1
    25. })
    26. }
    27. function changeName() {
    28. // setName('jack')
    29. setName((name) => {
    30. return 'jack'
    31. })
    32. }
    33. return (
    34. 当前求和为{count}

    35. 我的名字是:{name}

    36. )
    37. }
    38. export default Demo;

    4.扩展4_EffectHook 

     Demo.jsx

    1. import React, {Component} from 'react';
    2. import ReactDOM from 'react-dom';
    3. // class Demo extends Component {
    4. // state = {count: 0}
    5. //
    6. // add = () => {
    7. // this.setState(state => ({count: state.count + 1}))
    8. // }
    9. //
    10. // unmount = () => {
    11. // ReactDOM.unmountComponentAtNode(document.getElementById('root'))
    12. // }
    13. //
    14. // componentDidMount() {
    15. // this.timer = setInterval(() => {
    16. // this.setState(state => ({count: state.count + 1}))
    17. // }, 1000)
    18. // }
    19. //
    20. // componentWillUnmount() {
    21. // clearInterval(this.timer)
    22. // }
    23. //
    24. // render() {
    25. // return (
    26. //
    27. //

      当前求和为{this.state.count}

    28. //
    29. //
    30. //
    31. // );
    32. // }
    33. // }
    34. function Demo() {
    35. const [count, setCount] = React.useState(0)
    36. React.useEffect(() => {
    37. let timer = setInterval(() => {
    38. setCount(count => count + 1)
    39. }, 1000)
    40. return () => {
    41. clearInterval(timer)
    42. }
    43. }, [])
    44. function add() {
    45. setCount(count + 1)
    46. }
    47. function unmount() {
    48. ReactDOM.unmountComponentAtNode(document.getElementById('root'))
    49. }
    50. return (
    51. 当前求和为{count}

    52. )
    53. }
    54. export default Demo;

    5.扩展5_RefHook

    Demo.jsx

    1. import React, {Component} from 'react';
    2. import ReactDOM from 'react-dom';
    3. // class Demo extends Component {
    4. // state = {count: 0}
    5. //
    6. // myRef = React.createRef()
    7. //
    8. // add = () => {
    9. // this.setState(state => ({count: state.count + 1}))
    10. // }
    11. //
    12. // unmount = () => {
    13. // ReactDOM.unmountComponentAtNode(document.getElementById('root'))
    14. // }
    15. //
    16. // show = () => {
    17. // alert(this.myRef.current.value)
    18. // }
    19. //
    20. // componentDidMount() {
    21. // this.timer = setInterval(() => {
    22. // this.setState(state => ({count: state.count + 1}))
    23. // }, 1000)
    24. // }
    25. //
    26. // componentWillUnmount() {
    27. // clearInterval(this.timer)
    28. // }
    29. //
    30. // render() {
    31. // return (
    32. //
    33. // type="text" ref={this.myRef}/>
    34. //

      当前求和为{this.state.count}

    35. //
    36. //
    37. //
    38. //
    39. // );
    40. // }
    41. // }
    42. function Demo() {
    43. const [count, setCount] = React.useState(0)
    44. const myRef = React.useRef()
    45. React.useEffect(() => {
    46. let timer = setInterval(() => {
    47. setCount(count => count + 1)
    48. }, 1000)
    49. return () => {
    50. clearInterval(timer)
    51. }
    52. }, [])
    53. function add() {
    54. setCount(count + 1)
    55. }
    56. function show() {
    57. alert(myRef.current.value)
    58. }
    59. function unmount() {
    60. ReactDOM.unmountComponentAtNode(document.getElementById('root'))
    61. }
    62. return (
    63. type="text" ref={myRef}/>
    64. 当前求和为{count}

    65. )
    66. }
    67. export default Demo;

    6.扩展6_Fragment

    作用

    可以不用必须有一个真实的DOM根标签了

    Demo.jsx

    1. import React, {Component, Fragment} from 'react';
    2. class Demo extends Component {
    3. render() {
    4. return (
    5. type="text"/>
    6. type="text"/>
    7. );
    8. }
    9. }
    10. export default Demo;

    7.扩展7_Context

     理解

    一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信

    使用

    注意

     Demo.jsx

    1. import React, {Component} from 'react';
    2. import './Demo.css'
    3. const MyContext = React.createContext()
    4. const {Provider, Consumer} = MyContext
    5. export default class A extends Component {
    6. state = {username: 'tom', age: 18}
    7. render() {
    8. const {username, age} = this.state
    9. return (
    10. "parent">
    11. 我是A组件

    12. 我的用户名是:{username}

    13. );
    14. }
    15. }
    16. class B extends Component {
    17. render() {
    18. return (
    19. "child">
    20. 我是B组件

    21. );
    22. }
    23. }
    24. // class C extends Component {
    25. // static contextType = MyContext
    26. //
    27. // render() {
    28. // const {username, age} = this.context
    29. // return (
    30. //
      "grand">
    31. //

      我是C组件

    32. //

      我从A组件接收到的用户名:{username},年龄是{age}

    33. //
    34. // );
    35. // }
    36. // }
    37. function C() {
    38. return (
    39. "grand">
    40. 我是C组件

    41. 我从A组件接收到的用户名:

    42. {
    43. value => {
    44. return `${value.username},年龄是${value.age}`
    45. }
    46. }
    47. )
    48. }

    Demo.css

    1. .parent {
    2. width: 500px;
    3. background-color: orange;
    4. padding: 8px;
    5. }
    6. .child {
    7. width: 100%;
    8. background-color: skyblue;
    9. padding: 8px;
    10. }
    11. .grand {
    12. width: 100%;
    13. background-color: gray;
    14. padding: 8px;
    15. }

    8.扩展8_PureComponent

    组件优化

    原因

    解决

    办法一:Demo.jsx

    1. import React, {Component} from 'react';
    2. import './Demo.css'
    3. class Parent extends Component {
    4. state = {carName: "奔驰c36"}
    5. changeCar = () => {
    6. this.setState({})
    7. }
    8. shouldComponentUpdate(nextProps, nextState, nextContext) {
    9. console.log(this.props, this.state, 'Parent')
    10. console.log(nextProps, nextState, 'Parent')
    11. return !this.state.carName === nextState.carName
    12. }
    13. render() {
    14. console.log('Parent--render')
    15. const {carName} = this.state
    16. return (
    17. "parent">
    18. 我是Parent组件

    19. 我的车名字是:{carName}

    20. );
    21. }
    22. }
    23. class Child extends Component {
    24. shouldComponentUpdate(nextProps, nextState, nextContext) {
    25. console.log(this.props, this.state, 'Child')
    26. console.log(nextState, nextState, 'Child')
    27. return !this.props.carName === nextState.carName
    28. }
    29. render() {
    30. console.log('Child--render')
    31. return (
    32. "child">
    33. 我是Child组件

    34. 我接到的车是:{this.props.carName}
    35. );
    36. }
    37. }
    38. export default Parent;

     Demo.css

    1. .parent {
    2. background-color: orange;
    3. padding: 10px;
    4. }
    5. .child {
    6. background-color: gray;
    7. margin-top: 30px;
    8. padding: 10px;
    9. }

    办法二:Demo.jsx

    1. import React, {PureComponent} from 'react';
    2. import './Demo.css'
    3. class Parent extends PureComponent {
    4. state = {carName: "奔驰c36", stus: ['小张', '小李', '小王']}
    5. addStu = () => {
    6. // const {stus} = this.state
    7. // stus.unshift('小刘')
    8. // this.setState({stus: stus})
    9. const {stus} = this.state
    10. this.setState({stus: ['小刘', ...stus]})
    11. }
    12. changeCar = () => {
    13. // this.setState({carName: "迈巴赫"})
    14. const obj = this.state
    15. obj.carName = '迈巴赫'
    16. console.log(obj === this.state)
    17. this.setState(obj)
    18. }
    19. // shouldComponentUpdate(nextProps, nextState, nextContext) {
    20. // console.log(this.props, this.state, 'Parent')
    21. // console.log(nextProps, nextState, 'Parent')
    22. // return !this.state.carName === nextState.carName
    23. // }
    24. render() {
    25. console.log('Parent--render')
    26. const {carName} = this.state
    27. return (
    28. "parent">
    29. 我是Parent组件

    30. {this.state.stus} 
    31. 我的车名字是:{carName}

    32. "奥拓">
    33. );
    34. }
    35. }
    36. class Child extends PureComponent {
    37. // shouldComponentUpdate(nextProps, nextState, nextContext) {
    38. // console.log(this.props, this.state, 'Child')
    39. // console.log(nextState, nextState, 'Child')
    40. // return !this.props.carName === nextState.carName
    41. // }
    42. render() {
    43. console.log('Child--render')
    44. return (
    45. "child">
    46. 我是Child组件

    47. 我接到的车是:{this.props.carName}
    48. );
    49. }
    50. }
    51. export default Parent;

    9.扩展9_renderProps

    如何向组件内部动态传入带内容的结构(标签)?

    children props

    render props

    Demo.jsx

    1. import React, {Component} from 'react';
    2. import './Demo.css'
    3. class Parent extends Component {
    4. render() {
    5. return (
    6. "parent">
    7. 我是Parent组件

    8. );
    9. }
    10. }
    11. class A extends Component {
    12. state = {name: 'tom'}
    13. render() {
    14. const {name} = this.state
    15. return (
    16. "a">
    17. 我是A组件

    18. {this.props.render(name)}
    19. )
    20. }
    21. }
    22. class B extends Component {
    23. render() {
    24. return (
    25. "b">
    26. 我是B组件,{this.props.name}

    27. )
    28. }
    29. }
    30. export default Parent;

     Demo.css

    1. .parent {
    2. background-color: orange;
    3. padding: 10px;
    4. }
    5. .a {
    6. background-color: gray;
    7. margin-top: 30px;
    8. padding: 10px;
    9. }
    10. .b {
    11. background-color: skyblue;
    12. margin-top: 30px;
    13. padding: 10px;
    14. }

    10.扩展10_ErrorBoundary

    理解:

    特点:

    使用方式:

    1. // 生命周期函数,一旦后代组件报错,就会触发
    2. static getDerivedStateFromError(error) {
    3. console.log(error);
    4. // 在render之前触发
    5. // 返回新的state
    6. return {
    7. hasError: true,
    8. };
    9. }
    10. componentDidCatch(error, info) {
    11. // 统计页面的错误。发送请求发送到后台去
    12. console.log(error, info);
    13. }

    Parent.jsx

    1. import React, {Component} from 'react';
    2. import Child from "./Child";
    3. class Parent extends Component {
    4. state = {
    5. hasError: ''
    6. }
    7. //当Parent的子组件出现报错时候,会触发getDerivedStateFromError调用,并携带错误信息
    8. static getDerivedStateFromError(error) {
    9. console.log(error)
    10. return {hasError: error}
    11. }
    12. componentDidCatch(error, errorInfo) {
    13. console.log('渲染组件时出错')
    14. }
    15. render() {
    16. return (
    17. 我是Parent组件

    18. {this.state.hasError ?

      当前网络不稳定,稍后再试

      : }
    19. );
    20. }
    21. }
    22. export default Parent;

    Child.jsx

    1. import React, {Component} from 'react';
    2. class Child extends Component {
    3. state = {
    4. // users: [
    5. // {id: '001', name: 'tom', age: 18},
    6. // {id: '002', name: 'jack', age: 19},
    7. // {id: '003', name: 'peiqi', age: 20},
    8. // ]
    9. users: 'abc'
    10. }
    11. render() {
    12. return (
    13. 我是Child组件

    14. {
    15. this.state.users.map((userObj) => {
    16. return

      {userObj.name}-----{userObj.age}

    17. })
    18. }
    19. );
    20. }
    21. }
    22. export default Child;

    11.组件通信方式总结

    组件间的关系:

    几种通信方式:

    1. 1.props:
    2. (1).children props
    3. (2).render props
    4. 2.消息订阅-发布:
    5. pubs-sub、event等等
    6. 3.集中式管理:
    7. redux、dva等等
    8. 4.conText:
    9. 生产者-消费者模式

     比较好的搭配方式:

  • 相关阅读:
    性能测试分类
    Scalable Object Detection using Deep Neural Networks
    vs中集成vcpkg
    【Flink入门修炼】1-4 Flink 核心概念与架构
    搭建游戏要选什么样的服务器?
    ROS三种通信方式之话题通信
    DTK Barcode Recognition SDK Crack
    前后端分离项目(九):实现"添加"功能(后端接口)
    nginx安装与使用(入门)
    Qt:多语言支持,构建全面应用程序“
  • 原文地址:https://blog.csdn.net/qq_56444564/article/details/134114951