react面试题回顾

235 阅读6分钟

http

http各版本升级

  • http1 停等协议,头信息重复传输
  • http2 实现了多路复用,头信息压缩。不过依旧需要建立tcp3次链接时间和堵塞等待丢包堵塞,速度慢

image.png

  • http3 udp协议,无链接,速度等快 HTTP/3 通过 QUIC 协议提供了更快的连接建立时间和更好的性能,尤其在高延迟和高丢包率的网络环境下效果更为显著。 缺点:不安全(可伪造ip地址),浏览器和

选择使用 HTTP/3 还是 WebSocket 取决于您的具体需求和环境。

  • https

http+ssl=https

image.png

image.png

Vue是怎么实现渲染的

Vue 和 jQuery 是两种不同的前端框架/库,它们在渲染上存在一些重要的区别:

  1. 数据驱动 vs DOM 操作:

    • Vue: Vue 是一种数据驱动的框架,它使用声明式的语法将数据和 DOM 绑定在一起。您可以在 Vue 实例中定义数据,并使用模板语法将数据动态地渲染到 DOM 中。Vue 会自动响应数据的变化并更新 DOM。
    • jQuery: jQuery 是一个库,主要用于简化 DOM 操作。您可以使用 jQuery 来选择元素、修改元素的属性和内容、处理事件等。与 Vue 不同,jQuery 并不是数据驱动的,您需要手动操作 DOM 来实现视图的更新。
  2. 组件化 vs 命令式:

    • Vue: Vue 支持组件化开发,允许您将页面拆分为多个独立的组件,每个组件都有自己的状态和行为。Vue 组件提供了更好的封装性和复用性,使得代码更易于维护和扩展。
    • jQuery: jQuery 主要是通过选择器和操作函数来修改页面的元素。虽然可以将一些功能封装为插件,但并没有像 Vue 那样提供明确的组件化开发方式。
  3. 响应式 vs 手动更新:

    • Vue: Vue 提供了响应式的数据绑定机制,当数据发生变化时,相关的 DOM 会自动更新。这意味着您无需手动更新 DOM,而是通过修改数据来更新视图。
    • jQuery: 在 jQuery 中,您需要手动编写代码来更新 DOM。如果数据发生变化,您需要手动选择要更新的元素,并将新的数据渲染到相应的位置。
  4. 生态系统:

    • Vue: Vue 生态系统提供了丰富的工具和插件,如 Vue Router、Vuex、Vue CLI 等,为开发者提供了完整的解决方案。
    • jQuery: jQuery 是一个轻量级的库,提供了一些基本的 DOM 操作功能,但并不包含像 Vue 那样完整的生态系统。

jonny-wei.github.io/blog/vue/vu…

props 的变动,是否会引起 state hook 中数据的变动?

React 组件的 props 变动,会让组件重新执行,但并不会引起 state 的值的变动。state 值的变动,只能由 setState() 来触发。因此若想在 props 变动时,重置 state 的数据,需要监听 props 的变动,如:

const App = props => {
  const [count, setCount] = useState(0);

  // 监听 props 的变化,重置 count 的值
  useEffect(() => {
    setCount(0);
  }, [props]);

  return <div onClick={() => setCount(count + 1)}>{count}</div>;
};

基于 React 框架的特点,可以有哪些优化措施?

  1. 使用 React.lazy 和 Suspense 将页面设置为懒加载,避免 js 文件过大;
  2. 使用 SSR 同构直出技术,提高首屏的渲染速度;
  3. 使用 useCallback 和 useMemo 缓存函数或变量;使用 React.memo 缓存组件;
  4. 尽量调整样式或 className 的变动,减少 jsx 元素上的变动,尽量使用与元素相关的字段作为 key,可以减少 diff 的时间(React 会尽量复用之前的节点,若 jsx 元素发生变动,就需要重新创建节点);
  5. 对于不需要产生页面变动的数据,可以放到 useRef()中;

什么是闭包1.0

useEffect、useMemo、useCallback都是自带闭包的。每一次组件的渲染,它们都会捕获当前组件函数上下文中的状态(state, props),所以每一次这三种hooks的执行,反映的也都是当前的状态,你无法使用它们来捕获上一次的状态。

尽管由于定时器的存在,组件始终会一直重新渲染,但定时器的回调函数是挂载期间定义的,所以它的闭包永远是对挂载时 Counter 作用域的引用,故 count 永远不会超过 1。

const App = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(timer);
  }, []);

  return <div className="App">{count}</div>;
};

解决办法

const App = () => {
  const [count, setCount] = useState(0);

  // 监听 count 的变化,不过这里将定时器改成了 setTimeout
  // 即使不修改,setInterval()的timer也会在每次渲染时被清除掉,
  // 然后重新启动一个新的定时器
  useEffect(() => {
    const timer = setTimeout(() => {
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(timer);
  }, [count]);

  // 以回调的方式
  // 回调的方式,会计算回调的结果,然后作为下次更新的初始值
  // 详情可见: https://www.xiabingbao.com/post/react/react-usestate-rn5bc0.html#5.+updateReducer
  useEffect(() => {
    const timer = setInterval(() => {
      setCount(count => count + 1);
    }, 1000);
    return () => clearInterval(timer);
  }, []);

  return <div className="App">{count}</div>;
};

或者封装

const App = () => {
  const [count, setCount] = useState(0);

  // 监听 count 的变化,不过这里将定时器改成了 setTimeout
  // 即使不修改,setInterval()的timer也会在每次渲染时被清除掉,
  // 然后重新启动一个新的定时器
  useEffect(() => {
    const timer = setTimeout(() => {
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(timer);
  }, [count]);

  // 以回调的方式
  // 回调的方式,会计算回调的结果,然后作为下次更新的初始值
  // 详情可见: https://www.xiabingbao.com/post/react/react-usestate-rn5bc0.html#5.+updateReducer
  useEffect(() => {
    const timer = setInterval(() => {
      setCount(count => count + 1);
    }, 1000);
    return () => clearInterval(timer);
  }, []);

  return <div className="App">{count}</div>;
};

闭包2.0

import React, {useState, useEffect} from "react";
export default function UpdateTitleEffectHook() {
    const [number, setNumber] = useState(0)
    useEffect(() => {
        document.title = `${number}`
        console.log(`执行更新:${number}`)
        return ()=>{
            console.log(`清除上一次副作用:${number}`)
        }
    })
    return (
        <>
            <p>{number}</p>
            <button onClick={() => setNumber(number + 1)}>+</button>
        </>
    )
}

那么为什么在浏览器渲染完后,再执行清理的方法还能找到上次的state呢?原因很简单,我们在useEffect中返回的是一个函数,这形成了一个闭包,这能保证我们上一次执行函数存储的变量不被销毁和污染。

hook

react hooks 的出现,是对 react 中无状态组件的一种升级,使得函数组件也能state 和 生命周期

React Hooks 要解决的问题是状态共享,是继 render-props(渲染属性) 和 higher-order components(HOC;高阶组件) 之后的第三种状态逻辑复用方案,不会产生 JSX 嵌套地狱问题。

reacthook api

useContext

Context 提供了一种方式,能够让数据在组件树中传递时不必一级一级的手动传递

状态存储api

Usecallback 和useDemo的区别

共同作用:仅仅 依赖数据 发生变化, 才会重新计算结果,也就是起到缓存的作用。

  • useCallback缓存函数的引用,如在一些场景中一些函数是没有必要被重新刷新的,此时就应该缓存起来,提高性能,和减少资源浪费。
  • useMemo缓存计算数据的值,如: 需要计算的状态

useEffect 和useLayoutEffect的区别

  • useEffect里面的操作需要处理DOM,并且会改变页面的样式,就需要用这个,否则可能会出现出现闪屏问题,

  • useLayoutEffect里面的callback函数会在DOM更新完成后立即执行,但是会在浏览器进行任何绘制之前运行完成,阻塞了浏览器的绘制.

  • useLayoutEffect和平常写的ClassComponent的'componentDidMount'和'componentDidUpdate'同时执行。

  • useEffect会在本次更新完成后,也就是第1点的方法执行完成后,在开启一次任务调度,在下次任务调度中执行useEffect。

数据传递api

  • useRef 用于父子之间传值,操作dom