第三十七章 扩展知识点 1

简介: 第三十七章 扩展知识点

1、setState

(1). setState(stateChange, [callback])------对象式的setState
            1.stateChange为状态改变对象(该对象可以体现出状态的更改)
            2.callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
  (2). setState(updater, [callback])------函数式的setState
            1.updater为返回stateChange对象的函数。
            2.updater可以接收到state和props。
            4.callback是可选的回调函数, 它在状态更新、界面也更新后(render调用后)才被调用。
总结:
    1.对象式的setState是函数式的setState的简写方式(语法糖)
    2.使用原则:
        (1).如果新状态不依赖于原状态 ===> 使用对象方式
        (2).如果新状态依赖于原状态 ===> 使用函数方式
        (3).如果需要在setState()执行后获取最新的状态数据, 
          要在第二个callback函数中读取
写法一:对象式
import React, { Component } from 'react'
export default class Demo extends Component {
  state = {count:0}
  addCount = () => {
    // 获取原来的状态值
    const {count} = this.state
    // 更新状态值
    this.setState({count:count + 1},()=>{
      console.log('callback里面的状态',this.state.count)
    })
    // 监测查看状态值
    console.log('callback外面的状态',this.state.count)
  }
  render() {
    return (
      <div>
        <h1>当前求和为:{this.state.count}</h1>
        <button onClick={this.addCount}>点我+1</button>
      </div>
    )
  }
}

以上代码,就是一个简单的数字相加的功能,当我点击按钮【点我+1】的时候,状态值自增1。但是这里我们需要关注的是查看调用setState()方法后,在其callback内部与外部打印的状态值是否一样。


这里我们看到更新后打印的状态值是不一样的,在调用setState方法后,组件的状态并不会立即改变,而是在下一次渲染时才会更新。如果你在setState方法调用后立即打印组件的状态,你会发现它并没有发生变化。这是因为setState方法只是向React内部发出了一个更新组件状态的请求,而实际的更新过程是在下一次渲染时才会进行的。如果你需要及时获取组件的最新状态,你可以在组件的shouldComponentUpdate方法中进行判断,并在需要的时候调

setState方法进行更新。

写法二:函数式
import React, { Component } from 'react'
export default class Demo extends Component {
  state = {count:0}
  addCount = () => {
    // 获取原来的状态值
    const {count} = this.state
    // 更新状态值
    this.setState((state,props)=>({count:count + 1}),()=>{
      console.log('callback里面的状态',this.state.count)
    })
    // 监测查看状态值
    console.log('callback外面的状态',this.state.count)
  }
  render() {
    return (
      <div>
        <h1>当前求和为:{this.state.count}</h1>
        <button onClick={this.addCount}>点我+1</button>
      </div>
    )
  }
}

函数式就是第一个参数传递的是一个函数,它可以接收两个参数(state,props),返回值是一个状态对象。


2、LazyLoad

路由组件的懒加载

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

案例代码

import React, { Component, lazy, Suspense } from 'react'
import { NavLink, Route, Routes } from 'react-router-dom'
const Home = lazy(() => import('./Home'))
const About = lazy(() => import('./About'))
export default class Demo extends Component {
  render() {
    return (
      <div>
        <div className="row">
          <div className="col-xs-offset-2 col-xs-8">
            <div className="page-header">
              <h2>React Router Demo</h2>
            </div>
          </div>
        </div>
        <div className="row">
          <div className="col-xs-2 col-xs-offset-2">
            <div className="list-group">
              <NavLink className="list-group-item" to="/home">
                Home
              </NavLink>
              <NavLink className="list-group-item" to="/about">
                About
              </NavLink>
            </div>
          </div>
          <div className="col-xs-6">
            <div className="panel">
              <div className="panel-body">
                <Suspense fallback={<h1>Loading...</h1>}>
                  <Routes>
                    <Route path="/home" element={<Home />} />
                    <Route path="/about" element={<About />} />
                  </Routes>
                </Suspense>
              </div>
            </div>
          </div>
        </div>
      </div>
    )
  }
}

这里懒加载引入组件,必须配合Suspense使用,不然会报错。

原来普通引入的组件,加载页面的时候会把所有组件一次性加载完,现在使用懒加载后,当你用到该组件的时候才会去动态引入。

这种做法有以下几个好处:

  1. 提高网页加载速度:如果网页中的图片、CSSJavaScript等资源都是懒加载的,那么当用户第一次访问网页时,只会加载必要的资源,而不是全部资源。这样就可以大大减少页面加载时间,提高用户体验。
  2. 减少页面内存占用:如果网页中的资源全部都是懒加载的,那么在页面加载时就不会一次性加载完所有资源,这样就可以避免内存不足的问题。
  3. 提高网站安全性:懒加载可以减少网站被黑客攻击的风险。因为懒加载可以避免在页面加载时全部资源都加载到浏览器缓存中,这样就可以避免攻击者利用缓存中的资源来攻击网站。
  4. 方便后续维护:如果网页中的资源是懒加载的,那么在后续维护时就可以更方便地修改或删除资源。这样可以减少对网站的影响,提高维护效率。

3、State Hook ===> React.useState()

(1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作
(2). 语法: const [xxx, setXxx] = React.useState(initValue)  
(3). useState()说明:
        参数: 第一次初始化指定的值在内部作缓存
        返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数
(4). setXxx()2种写法:
        setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
        setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值

案例代码:

import React from 'react'
export default function Demo () {
  const [count,setCount] = React.useState(0)
  function addCount() {
    setCount(count + 1)
  }
  return (
    <div>
      <h1>当前求和为:{count}</h1>
      <button onClick={addCount}>点我+1</button>
    </div>
  )

同样是一个点击加1的功能组件,只不过由类式组件改成了函数式组件。

关键代码:

const [count,setCount] = React.useState(0)
  • count: 内部当前的状态值
  • setCount: 操作该状态的方法

其中setCount有两种写法:

  • setCount( count + 1), 参数直接是一个值
  • setCount( oldCount => oldCount + 1),参数是一个函数,内部可以介绍旧的状态,返回一个新的状态

4、Effect Hook ===> React.useEffect()

(1). Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
(2). React中的副作用操作:
        发ajax请求数据获取
        设置订阅 / 启动定时器
        手动更改真实DOM
(3). 语法和说明: 
        useEffect(() => { 
          // 在此可以执行任何带副作用操作
          return () => { // 在组件卸载前执行
            // 在此做一些收尾工作, 比如清除定时器/取消订阅等
          }
        }, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行
(4). 可以把 useEffect Hook 看做如下三个函数的组合
        componentDidMount()
        componentDidUpdate()
      componentWillUnmount() 

案例代码:

import React from 'react'
import root from '../../index'
export default function Demo () {
  const [count,setCount] = React.useState(0)
  React.useEffect(()=>{
    let timer = setInterval(() => {
      console.log('@@@')
      setCount( count + 1)
    }, 1000);
    return () => {
      clearInterval(timer)
    }
  })
  function addCount() {
    setCount(count + 1)
  }
  function unmount () {
    root.unmount()
  }
  return (
    <div>
      <h1>当前求和为:{count}</h1>
      <button onClick={addCount}>点我+1</button>
      <button onClick={unmount}>点击卸载组件</button>
    </div>
  )
}

以上代码,打开页面就会每隔1秒自增1,新增卸载组件功能。

关键代码1:

import root from '../../index'
//-----------------------------
  function unmount () {
    root.unmount()
  }

react18.x版本中,卸载组件需要使用root.unmount()

关键代码2:

React.useEffect(()=>{
    let timer = setInterval(() => {
      console.log('@@@')
      setCount( count + 1)
    }, 1000);
    return () => {
      clearInterval(timer)
    }
  })

在副作用函数中,开启了一个定时器,在返回的函数中清除了定时器。

使用useEffect模拟componentDidMount

import React, { useEffect } from 'react';
function MyComponent() {
  useEffect(() => {
    // 在这里执行您的副作用操作,例如 API 调用等
    console.log('componentDidMount');
    // 如果需要在组件卸载时执行清理操作,请返回一个函数
    return () => {
      console.log('componentWillUnmount');
    };
  }, []); // 空数组表示没有依赖项,因此副作用函数仅在组件挂载时运行
  return <div>MyComponent</div>;
}

要在函数组件中模拟 componentDidMount,您可以使用 useEffect 并传递一个空数组 [] 作为依赖项。这将确保副作用函数仅在组件挂载时运行一次。

使用useEffect模拟componentDidUpdate

import React, { useEffect } from 'react';
function MyComponent({ someProp }) {
  useEffect(() => {
    // 在这里执行您的副作用操作,例如根据 prop 更改更新数据等
    console.log('componentDidUpdate');
    // 如果需要在组件卸载时执行清理操作,请返回一个函数
    return () => {
      console.log('componentWillUnmount');
    };
  }, [someProp]); // 将需要观察的变量添加到依赖项数组中
  return <div>MyComponent</div>;
}

要模拟 componentDidUpdate,您可以使用 useEffect,并将需要观察的变量添加到依赖项数组中。这将确保副作用函数在依赖项更改时运行。

使用useEffect模拟componentWillUnmount

React.useEffect(()=>{
    // 开启一个定时器
  let timer = setInterval(()=>{
    console.log('开启副作用')
    },1000)
    // 这里return的函数,可以当做componentWillUnmount,在这里清除副作用
    return () => {
      clearInterval(timer)
      console.log('清除副作用')
    }
},[])

要模拟 componentWillUnmount,您可以在 useEffect 的副作用函数中返回一个函数。这个返回的函数将在组件卸载时执行。


5、Ref Hook ===> React.useRef()

(1). Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
(2). 语法: const refContainer = useRef()
(3). 作用:保存标签对象,功能与React.createRef()一样

React 中,useRef 是一个非常有用的 Hook,它可以帮助您在函数组件中创建和访问可变的引用。useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传递的参数(默认为null)。这个ref对象在组件的整个生命周期内保持不变。

以下是如何在 React 中使用 useRef

创建一个 ref

import React, { useRef } from 'react';
function MyComponent() {
  const myRef = useRef(null);
  // ...
}

使用 ref

您可以使用创建的 ref 来引用 DOM 元素或其他 React 组件。要将 ref 附加到 DOM 元素,只需将 ref 传递给元素的 ref 属性。

import React, { useRef } from 'react';
function MyComponent() {
  const myRef = useRef(null);
  return (
    <div>
      <input ref={myRef} />
    </div>
  );
}

现在,myRef.current 将指向输入元素。

访问 ref 的值

要访问 ref 的值,您可以使用 .current 属性。例如,您可以在事件处理程序中访问输入元素的值。

import React, { useRef } from 'react';
function MyComponent() {
  const myRef = useRef(null);
  const handleClick = () => {
    console.log('Input value:', myRef.current.value);
  };
  return (
    <div>
      <input ref={myRef} />
      <button onClick={handleClick}>Log input value</button>
    </div>
  );
}

在这个示例中,当用户点击按钮时,输入元素的值将被记录到控制台。

通过这些示例,您可以了解如何在 React 中使用 useRef。请注意,useRef 不仅可以用于访问 DOM 元素,还可以用于存储任何可变值,而不会触发组件重新渲染 。

第三十七章 扩展知识点2:https://developer.aliyun.com/article/1409377

相关文章
|
7天前
|
XML JSON Java
Java开发常用代码总结和分享
Java开发常用代码总结和分享
|
2月前
|
前端开发 JavaScript
第三十七章 扩展知识点2
第三十七章 扩展知识点
|
12月前
|
存储 数据管理 数据挖掘
这几句话让我彻底明白了什么是元数据
这几句话让我彻底明白了什么是元数据
|
存储 开发者
彻底搞懂函数,读这篇文章就够了
如果你之前使用过任何一门编程语言,那么对于你来讲想必已经知道什么是函数,以及如何使用函数了,那你大可不必往下读了。这篇文章是写给新手看的,也就是说我假设你对于函数没有任何的概念。 我们就先从什么是函数来说起吧!
84 0
|
XML JSON 运维
Linux脚本是干什么的?底层原理是什么?
Linux脚本是干什么的?底层原理是什么?
335 0
|
移动开发 JSON 小程序
【小程序开篇】小程序架构和配置
【小程序开篇】小程序架构和配置
255 0
【小程序开篇】小程序架构和配置
|
存储 NoSQL 算法
Redis集群详述(从服务内部讲解,这次看完真的懂了,面试官再怎么问也能轻轻松松!)
Redis集群详述(从服务内部讲解,这次看完真的懂了,面试官再怎么问也能轻轻松松!)
205 0
Redis集群详述(从服务内部讲解,这次看完真的懂了,面试官再怎么问也能轻轻松松!)
一个demo让你彻底搞懂线程池工作流程(看不懂评论区留言喷我)
线程池无非就那几个参数,啥核心线程、最大线程、队列,没啥难的,有手就能学废 来,看完这篇文章还不懂的评论区留言喷我
123 0
一个demo让你彻底搞懂线程池工作流程(看不懂评论区留言喷我)
|
设计模式 缓存 前端开发
可否举例说明你在工作中是如何优化前端代码的?
可否举例说明你在工作中是如何优化前端代码的?
164 0
|
机器学习/深度学习 存储 监控