likes
comments
collection
share

前端React面试基础系列(React基础篇)

作者站长头像
站长
· 阅读数 4

React 基础系列

1. 什么是受控组件和非受控组件?

受控组件

像表单元素在用户输入时,像<input> <select>等元素需要绑定一个 change 事件,当组件的状态发生变化时就会触发 change 事件,更新组件的 state,这种就是受控组件。

非受控组件

如果一个表单组件没有 value、props 时,就可以称为非受控组件。 非受控组件可以使用 ref 来从 DOM 获取到表单的值。

2. 类组件和函数组件有什么区别?

3. state 和 props 的区别

state

state 时用来存储组件中的状态值,必须要使用 setState 来修改,state 值的变化会造成组件的重新渲染。

props

props 时一个外部传入到组件内的参数,具有可读性和不可变性,只能通过外部组件来传入新的 Props 来重新渲染子组件。

区别

  1. props 是不可修改的,state 是在组件中被创建,可以通过 setState 来进行修改的。
  2. props 是传递给组件的,state 则是组件自身内部管理的。

为什么 props 是只读的? 因为 React 的设计中,是根据单向数据流的设计模式,使状态可预测。如果子组件可以修改 props 的值,那么就会造成状态的不可预测性,给后续的维护及调试带来很大的困扰。

4. 父子组件的通信方式

  1. props 和 callback 方式
    • 父组件 -> 通过自身 state 改变,重新渲染,传递 props -> 通知子组件
    • 子组件 -> 通过调用父组件 props 方法 -> 通知父组件。
  2. ref 方式
    • 类组件可以通过 ref 直接获取组件实例,实现组件通信
    • 函数组件 forwardRef + useImperativeHandle 实现组件通信
  3. React-redux 或 React-mobx 状态管理方式
    • 状态管理库
  4. context 上下文方式
    • 将一些数据存储在全局数据中
  5. event bus 事件总线(类似于 PubSub 库)
    • react 中并不推荐,因为需要手动绑定和解绑
    • 一定程度上违背了 React 数据流向原则
    • 小项目还好,大项目难以维护

5. 类组件的setState和函数组件的useState异同

相同点

都更新视图,底部调用了scheduleUpdateFiber方法,在事件驱动情况下都有批量更新规则。

不同点

  1. setState只要调用了就会执行更新;useState会浅比较2次state是否相同
  2. setState有专门监听变化的回调函数;useState只能通过useEffect
  3. setState底层处理上主要是和老的state合并;useState则重新赋值

6. 为什么React组件中 return 一个对象而不是一个元素时会报错

因为对象不具备迭代接口,必须要时原型或者自己身上有[Symbol.iterator]属性才可以,而数组是有迭代接口的,所以可以直接迭代。

7. 什么是 JSX

JSX 是一种表达式也是 React 的一种标准书写方式,允许我们使用书写 html 的方式去写 react 元素。

最终会变成什么

  1. jsx 元素节点首先会被 babel 编译成React.createElement形式
  2. createElement 处理之后,会被转换成 react element 对象。 前端React面试基础系列(React基础篇)
  3. 在调和阶段,React element 对象的每一个子节点都会形成一个与之对应的 fiber 对象,然后通过 siblingreturnchild 将每一个 fiber 对象联系起来。

babel工作原理

babel的一种工作原理(html 文件中 script 导入时):在 script 标签中,如果 type 不是text/javascript或者module,游览器不会去解析 javascript 内部的代码,babel 会监听全局的document.contentLoad(意味着当前页面所有的 script 标签全部生成完毕)。

babel 直接拿到所有的 script 标签,并读 script 上的属性getAttributes("type"),如果是text/babel,会把里面的代码全部拿过来,然后转换,生成新的 script 标签插入到页面。

8. 说说有哪些hooks

1. useState

用来声明状态变量,接受的参数是一个初始值;返回一个数组,数组的第[0]项是当前的状态值,[1]项是用来改变状态值的方法函数。

2. useEffect

副作用,react首次渲染和之后的每次渲染都可以调用一遍传给useEffect的函数,可以模拟类组件的3个生命周期:componentDidMountcomponentDidUpdatecomponentWillUnmount

当第二个参数传入一个空数组时,相当于只在首次渲染的时候执行;如果传入一个变量,就会进行一次浅比较,变量发生变化时,会执行传入的函数。

3. useRef

  • 可以获取当前元素的所有属性,并且返回一个可变的ref对象。
  • 可以用来缓存数据

不是仅为真实 dom 服务,构建一个状态出来,但是这个状态时直接脱离 react 控制的,他的变化也不会造成重新渲染,同时状态还不会因为组件的重新渲染而被初始化

如果不使用 useRef 去处理真实 dom 会出现什么问题?
  • 使用 state 会造成没必要的重新渲染,用全局变量又会造成闭包问题

4. useMemo(优化)

场景: 当一个父组件中调用了一个子组件的时候,父组件的 state 发生变化,会导致父组件更新,而子组件虽然没有发生改变,但也会进行更新。

  • useMemo可以减少不必要的渲染和循环;
  • 减少子组件的渲染次数;
  • 同时通过特定的依赖进行更新,避免很多不必要的开销。

5. useCallback(优化)

useMemo类似,useMemo返回的是函数运行的结果useCallback返回的是函数。这个函数是父组件传递子组件的一个函数,防止做无关的刷新,这个组件必须配合memo来使用。

6. useContext

就是类组件中的context,可以用来存储一些全局的状态。

7. useReducer

是一个用于状态管理的hook api,与reducer函数相关。她接受2个参数,分别为reducer函数和初始状态。返回一个数组,第[0]项是state值,第[1]项是dispatch函数。

8. useLayoutEffect

useEffect 几乎完全一致,唯一的区别是 useLayoutEffect 会在所有的 dom 变更之后同步调用(意味着会完全阻塞后续工作),而 useEffect 是在所有的 dom 变更之后异步调用。

9. useTransition(react18,优化)

const [isPending, startTransition] = useTransition()是一个帮助我们在不阻塞UI的情况下更新状态。

返回1个数组,[0]项告诉我们是否存在待处理的transition;[1]项是一个startTransition函数,用这个方法可以把状态更新标记为transition

function TabContainer() {  
    const [isPending, startTransition] = useTransition();  
    const [tab, setTab] = useState('about');  
    function selectTab(nextTab) {  
        startTransition(() => {  
            setTab(nextTab);  
        });  
    }  
    // ……
}

....

更多建议查看React官网react.docschina.org/reference/r…

9.fowardRef

是一个高阶组件,接收一个组件作为参数返回一个新的组件。给函数组件扩展了一个 ref 属性。 给子组件挂 ref 是要要求子组件去追加一个 forwardRef 的,同时 forwardRef 会将得到的这个 ref 属性通过第二个参数传递给真实的函数组件。

10.useImperativeHandle

第一个参数是 ref,意味着在底层会去改这个 ref 的 current 属性 第二个参数是一个函数,这个函数的返回值最终会被丢到这个 ref.current 属性上去 第三个参数是依赖项,意味着依赖项不变的话 ref 的 current 值不会被重新赋值

11. React18有哪些更新

  1. setState自动批处理

    • 17中只有react合成事件会进行批处理,legacy模式;
    • 18中所有事件都进行批处理,提高了性能,concurrent模式。
  2. 支持并发模式的渲染

  3. 去掉了对IE浏览器的支持

  4. flushSync,用于退出批量更新

  5. react组件返回值更新

    • 17中返回空组件只能返回null,返回undefined会报错
    • 18中支持null和undefined
  6. 支持useId(在服务器和客户端生成相同的唯一一个id,避免hydrating的不兼容)

  7. 新增hooksuseInsertionEffect:只建议在css in js库中使用,在dom生成之前执行,在useLayoutEffect之前,一般用于提前注入脚本

  8. useSyncExternalStore:解决外部数据撕裂问题

  9. Suspense不再需要fallback捕获

  10. Concurrent Mode:并发模式,可以帮助应用保持响应,根据用户的设备性能和网速进行调整,通过渲染可中断来修复阻塞渲染机制。该模式下,可以同时更新多个状态;

  11. strict mode更新:使用严格模式时,React会对每个组件返回两次渲染,以便你观察一些意想不到的结果,在react17中去掉了一次渲染的控制台日志,以便让日志容易阅读。react18取消了这个限制,第二次渲染会以浅灰色出现在控制台日志 ....

12. Redux工作原理

前端React面试基础系列(React基础篇)

场景

  • 跨层级组件数据共享与通信
  • 一些需要持久化的全局数据

工作原理

单例模式

主要构成

Store

全局状态管理对象

Reducer

一个纯函数,根据旧state和props更新state

Action

改变状态的唯一方式是调用dispatch函数,传递一个action给这个函数