react面试题(2204第二周)

本文详细介绍了React的核心特性,如组件化、虚拟DOM及其优势,以及生命周期方法,包括挂载、更新和卸载阶段。还讨论了setState的执行机制、事件处理、组件通信方式。此外,文章涵盖了Redux中间件的理解,如redux-thunk和redux-logger,以及React性能优化策略,如使用React.memo和PureComponent。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

react面试题




一、说说你对react的理解?有哪些特性?

React,用于构建用户界面的 JavaScript 库,只提供了 UI 层面的解决方案,遵循组件设计模式、声明式编程范式和函数式编程概念,以使前端应用程序更高效,使用虚拟 DOM 来有效地操作 DOM,遵循从高阶组件到低阶组件的单向数据流,帮助我们将界面成了各个独立的小块,每一个块就是组件,这些组件之间可以组合、嵌套,构成整体页面,react 类组件使用一个名为 render() 的方法或者函数组件return,接收输入的数据并返回需要展示的内容

class HelloMessage extends React.Component {
  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

ReactDOM.render(
  <HelloMessage name="Taylor" />,
  document.getElementById("hello-example")
);

上述这种类似 XML 形式就是 JSX,最终会被 babel 编译为合法的 JS 语句调用

被传入的数据可在组件中通过 this.props 在 render() 访问

二、说说Real DOM和Virtual DOM的区别?优缺点?

虚拟 DOM 不会进行排版与重绘操作,而真实 DOM 会频繁重排与重绘 虚拟 DOM 的总损耗是“虚拟 DOM 增删改+真实 DOM 差异增删改+排版与重绘”,真实 DOM 的总损耗是“真实 DOM 完全增删改+排版与重绘”

真实dom优点是:易用。缺点,效率低,解析速度慢,占用内存高,性能差
虚拟dom优点:方便简单,维护困难,性能提高,跨平台,缺点:无法针对性的极致优化,首次渲染慢

三,说说React生命周期有哪些不同的阶段?每个阶段对应的方法是?

(1)挂载阶段:

constructor() 在 React 组件挂载之前,会调用它的构造函数。

componentWillMount: 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。

componentDidMount(): 在组件挂载后(插入 DOM 树中)立即调用

(2)更新运行阶段:

componentWillReceiveProps: 在接受父组件改变后的props需要重新渲染组件时用到的比较多,外部组件传递 频繁的时候会导致效率比较低

shouldComponentUpdate():用于控制组件重新渲染的生命周期,state发生变化,组件会进入重新渲染的流 程,在这里return false可以阻止组件的更新

render(): render() 方法是 class 组件中唯一必须实现的方法。

componentWillUpdate()*: shouldComponentUpdate返回true以后,组件进入重新渲染完成之前进入这个函 数。

componentDidUpdate(): 每次state改变并重新渲染页面后都会进入这个生命周期

(3)卸载或销毁阶段:

componentWillUnmount (): 在此处完成组件的卸载和数据的销毁。

四,说说React中setState执行机制?

一个组件的显示形态可以由数据状态和外部参数所决定,而数据状态就是state, 当需要修改里面的值的状态需要通过调用setState来改变,从而达到更新组件内部数据的作用
setState第一个参数可以是一个对象,或者是一个函数,而第二个参数是一个回调函数,用于可以实时的获取到更新之后的数据
在使用setState更新数据的时候,setState的更新类型分成:同步更新,异步更新
在组件生命周期或React合成事件中,setState是异步
在setTimeout或者原生dom事件中,setState是同步
对同一个值进行多次 setState, setState 的批量更新策略会对其进行覆盖,取最后一次的执行结果

五,说说react的事件机制

React基于浏览器的事件机制自身实现了一套事件机制,包括事件注册、事件的合成、事件冒泡、事件派发等

在React中这套事件机制被称之为合成事件

React 上注册的事件最终会绑定在document这个 DOM 上,而不是 React 组件对应的 DOM(减少内存开销就是因为所有的事件都绑定在 document 上,其他节点没有绑定事件)
React 自身实现了一套事件冒泡机制,所以这也就是为什么我们 event.stopPropagation()无效的原因。
React 通过队列的形式,从触发的组件向父组件回溯,然后调用他们 JSX 中定义的 callback
React 有一套自己的合成事件 SyntheticEvent

六,react组件之间如何进行通信

父组件向子组件通信,可以通过 props 方式传递数据;也可以通过 ref 方式传递数据;
子组件向父组件通信,通过回调函数方式传递数据;
父组件向后代所有组件传递数据,如果组件层级过多,通过 props 的方式传递数据很繁琐,可以通过 Context.Provider 的方式;
一个数据源实现跨组件通信,通过指定 contextType 的方式来实现;
多个数据源实现跨组件通信,使用 Context.Consumer 方式实现;

七,说说你对受控组件和非受控组件的理解?应用场景?

受控组件,简单来讲,就是受我们控制的组件,组件的状态全程响应外部数据
这时候当我们在输入框输入内容的时候,会发现输入的内容并无法显示出来,也就是input标签是一个可读的状态

这是因为value被this.state.username所控制住。当用户输入新的内容时,this.state.username并不会自动更新,这样的话input内的内容也就不会变了

如果想要解除被控制,可以为input标签设置onChange事件,输入的时候触发事件函数,在函数内部实现state的更新,从而导致input框的内容页发现改变

因此,受控组件我们一般需要初始状态和一个状态更新事件函数

非受控组件,简单来讲,就是不受我们控制的组件
一般情况是在初始化的时候接受外部数据,然后自己在内部存储其自身状态
应用场景:大部分时候推荐使用受控组件来实现表单,因为在受控组件中,表单数据由React组件负责处理,如果选择非受控组件的话,控制能力较弱,表单数据就由DOM本身处理,但更加方便快捷,代码量少

在这里插入图片描述

七,react diff算法的理解

第一次render在执行的时候会将第一次的虚拟dom做一次缓存,第二次渲染的时候会将新的虚拟dom和老的虚拟dom进行对比。这个对比的过程其实就是diff算法。

八,说说你对redux中间件的理解?常用的中间件有哪些?实现原理

中间件(Middleware)是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用,能够达到资源共享、功能共享的目的

常用中间件:redux-thunk:用于异步操作
redux-logger:用于日志记录

export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    var store = createStore(reducer, preloadedState, enhancer);
    var dispatch = store.dispatch;
    var chain = [];

    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    };
    chain = middlewares.map(middleware => middleware(middlewareAPI));
    dispatch = compose(...chain)(store.dispatch);

    return {...store, dispatch}
  }
}

所有中间件被放进了一个数组chain,然后嵌套执行,最后执行store.dispatch。可以看到,中间件内部(middlewareAPI)可以拿到getState和dispatch这两个方法

在上面的学习中,我们了解到了redux-thunk的基本使用

内部会将dispatch进行一个判断,然后执行对应操作,原理如下:

function patchThunk(store) {
    let next = store.dispatch;

    function dispatchAndThunk(action) {
        if (typeof action === "function") {
            action(store.dispatch, store.getState);
        } else {
            next(action);
        }
    }

    store.dispatch = dispatchAndThunk;
}

实现一个日志输出的原理也非常简单,如下:

let next = store.dispatch;

function dispatchAndLog(action) {
  console.log("dispatching:", addAction(10));
  next(addAction(5));
  console.log("新的state:", store.getState());
}

store.dispatch = dispatchAndLog;

九,说说React jsx转换成真实DOM的过程

使用React.createElement或JSX编写React组件,实际上所有的 JSX 代码最后都会转换成React.createElement(…) ,Babel帮助我们完成了这个转换的过程。
createElement函数对key和ref等特殊的props进行处理,并获取defaultProps对默认props进行赋值,并且对传入的孩子节点进行处理,最终构造成一个虚拟DOM对象
ReactDOM.render将生成好的虚拟DOM渲染到指定容器上,其中采用了批处理、事务等机制并且对特定浏览器进行了性能优化,最终转换为真实DOM

十,说说你对@reduxjs/toolkit的理解?和react-redux有什么区别?

什么是reduxjs/toolkit?

Redux Toolkit 是我们官方推荐的编写 Redux 逻辑的方法。它围绕 Redux 核心,并包含我们认为对于构建 Redux 应用必不可少的软件包和功能。Redux Toolkit 建立在我们建议的最佳实践中,简化了大多数 Redux 任务,防止了常见错误,并使编写 Redux 应用程序更加容易。
React-redux是官方react UI绑定层,允许React组件从redux存储中读取数据,并将操作分派到存储以更新的状态。提供了connect,Provider等API,帮助我们连接react和redux,实现的逻辑会更加的严谨高效。
@reduxjs/tookit是对Redux的二次封装,开箱即用的一个高效的Redux开发工具,使得创建store,更新store

区别

1、reduxjs/tookit相对于react-redux来说比较方便,集成了redux-devtools-extension,不需要额外的配置,非常方便
2、reduxjs/tookit集成immutable-js的功能,不需要安装配置使用,提升了开发效率
3、reduxjs/tookit集成了redux-thunk的功能
4、reduxjs/tookit将types、actions、reducers放在一起组成了全新的slices,简化了我们的使用

十一,React性能优化的手段有哪些??

使用React.Memo来缓存组件
使用useMemo缓存大量的计算
使用React.PureComponent , shouldComponentUpdate
避免使用内联对象
避免使用匿名函数
延迟加载不是立即需要的组件
调整CSS而不是强制组件加载和卸载
使用React.Fragment避免添加额外的DOM

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值