字节前端一面经典 react 面试题及答案
setState 方法的第二个参数有什么用?使用它的目的是什么?
它是一个回调函数,当 setState 方法执行结束并重新渲染该组件时调用它。在工作中,更好的方式是使用 React 组件生命周期之——“存在期”的生命周期方法,而不是依赖这个回调函数。
React setState 笔试题,下面的代码输出什么
react 和 vue 的区别
相同点:
数据驱动页面,提供响应式的试图组件
都有 virtual DOM,组件化的开发,通过 props 参数进行父子之间组件传递数据,都实现了 webComponents 规范
数据流动单向,都支持服务器的渲染 SSR
都有支持 native 的方法,react 有 React native, vue 有 wexx
不同点:
数据绑定:Vue 实现了双向的数据绑定,react 数据流动是单向的
数据渲染:大规模的数据渲染,react 更快
使用场景:React 配合 Redux 架构适合大规模多人协作复杂项目,Vue 适合小快的项目
开发风格:react 推荐做法 jsx + inline style 把 html 和 css 都写在 js 了
vue 是采用 webpack +vue-loader 单文件组件格式,html, js, css 同一个文件
在哪个生命周期中你会发出 Ajax 请求?为什么?
Ajax 请求应该写在组件创建期的第五个阶段,即 componentDidMount 生命周期方法中。原因如下。在创建期的其他阶段,组件尚未渲染完成。而在存在期的 5 个阶段,又不能确保生命周期方法一定会执行(如通过 shouldComponentUpdate 方法优化更新等)。在销毀期,组件即将被销毁,请求数据变得无意义。因此在这些阶段发岀 Ajax 请求显然不是最好的选择。在组件尚未挂载之前,Ajax 请求将无法执行完毕,如果此时发出请求,将意味着在组件挂载之前更新状态(如执行 setState),这通常是不起作用的。在 componentDidMount 方法中,执行 Ajax 即可保证组件已经挂载,并且能够正常更新组件。
简述 flux 思想
Flux
的最大特点,就是数据的"单向流动"。
用户访问
View
View
发出用户的Action
Dispatcher
收到Action
,要求Store
进行相应的更新Store
更新后,发出一个"change"
事件View
收到"change"
事件后,更新页面
React 中的 StrictMode(严格模式)是什么??
React 的StrictMode
是一种辅助组件,可以帮助咱们编写更好的 react 组件,可以使用<StrictMode />
包装一组组件,并且可以帮咱们以下检查:
验证内部组件是否遵循某些推荐做法,如果没有,会在控制台给出警告。
验证是否使用的已经废弃的方法,如果有,会在控制台给出警告。
通过识别潜在的风险预防一些副作用。
参考 前端进阶面试题详细解答
使用 React Hooks 好处是啥?
首先,Hooks 通常支持提取和重用跨多个组件通用的有状态逻辑,而无需承担高阶组件或渲染 props
的负担。Hooks
可以轻松地操作函数组件的状态,而不需要将它们转换为类组件。Hooks 在类中不起作用,通过使用它们,咱们可以完全避免使用生命周期方法,例如 componentDidMount
、componentDidUpdate
、componentWillUnmount
。相反,使用像useEffect
这样的内置钩子。
在使用 React Router 时,如何获取当前页面的路由或浏览器中地址栏中的地址?
在当前组件的 props 中,包含 location 属性对象,包含当前页面路由地址信息,在 match 中存储当前路由的参数等数据信息。可以直接通过 this .props 使用它们。
React 实现的移动应用中,如果出现卡顿,有哪些可以考虑的优化方案
增加
shouldComponentUpdate
钩子对新旧props
进行比较,如果值相同则阻止更新,避免不必要的渲染,或者使用PureReactComponent
替代Component
,其内部已经封装了shouldComponentUpdate
的浅比较逻辑对于列表或其他结构相同的节点,为其中的每一项增加唯一
key
属性,以方便React
的diff
算法中对该节点的复用,减少节点的创建和删除操作render
函数中减少类似onClick={() => {doSomething()}}
的写法,每次调用 render 函数时均会创建一个新的函数,即使内容没有发生任何变化,也会导致节点没必要的重渲染,建议将函数保存在组件的成员对象中,这样只会创建一次组件的
props
如果需要经过一系列运算后才能拿到最终结果,则可以考虑使用reselect
库对结果进行缓存,如果 props 值未发生变化,则结果直接从缓存中拿,避免高昂的运算代价webpack-bundle-analyzer
分析当前页面的依赖包,是否存在不合理性,如果存在,找到优化点并进行优化
react 有什么优点
提高应用性能
可以方便的在客户端和服务端使用
使用 jsx 模板进行数据渲染,可读性好
在 Reducer 文件里,对于返回的结果,要注意哪些问题?
在 Reducer 文件里,对于返回的结果,必须要使用 Object.assign ( )来复制一份新的 state,否则页面不会跟着数据刷新。
createElement 过程
React.createElement(): 根据指定的第一个参数创建一个 React 元素
第一个参数是必填,传入的是似 HTML 标签名称,eg: ul, li
第二个参数是选填,表示的是属性,eg: className
第三个参数是选填, 子节点,eg: 要显示的文本内容
约束性组件( controlled component)与非约束性组件( uncontrolled component)有什么区别?
在 React 中,组件负责控制和管理自己的状态。如果将 HTML 中的表单元素( input、 select、 textarea 等)添加到组件中,当用户与表单发生交互时,就涉及表单数据存储问题。根据表单数据的存储位置,将组件分成约東性组件和非约東性组件。约束性组件( controlled component)就是由 React 控制的组件,也就是说,表单元素的数据存储在组件内部的状态中,表单到底呈现什么由组件决定。如下所示, username 没有存储在 DOM 元素内,而是存储在组件的状态中。每次要更新 username 时,就要调用 setState 更新状态;每次要获取 username 的值,就要获取组件状态值。
非约束性组件( uncontrolled component)就是指表单元素的数据交由元素自身存储并处理,而不是通过 React 组件。表单如何呈现由表单元素自身决定。如下所示,表单的值并没有存储在组件的状态中,而是存储在表单元素中,当要修改表单数据时,直接输入表单即可。有时也可以获取元素,再手动修改它的值。当要获取表单数据时,要首先获取表单元素,然后通过表单元素获取元素的值。注意:为了方便在组件中获取表单元素,通常为元素设置 ref 属性,在组件内部通过 refs 属性获取对应的 DOM 元素。
虽然非约東性组件通常更容易实现,可以通过 refs 直接获取 DOM 元素,并获取其值,但是 React 建议使用约束性组件。主要原因是,约東性组件支持即时字段验证,允许有条件地禁用/启用按钮,强制输入格式等。
根据下面定义的代码,可以找出存在的两个问题吗 ?
请看下面的代码:
答案:1.在构造函数没有将 props
传递给 super
,它应该包括以下行
2.事件监听器(通过addEventListener()
分配时)的作用域不正确,因为 ES6 不提供自动绑定。因此,开发人员可以在构造函数中重新分配clickHandler
来包含正确的绑定:
讲讲什么是 JSX ?
当 Facebook 第一次发布 React 时,他们还引入了一种新的 JS 方言 JSX
,将原始 HTML 模板嵌入到 JS 代码中。JSX 代码本身不能被浏览器读取,必须使用Babel
和webpack
等工具将其转换为传统的 JS。很多开发人员就能无意识使用 JSX,因为它已经与 React 结合在一直了。
React 的生命周期方法有哪些?
componentWillMount
:在渲染之前执行,用于根组件中的 App 级配置。componentDidMount
:在第一次渲染之后执行,可以在这里做 AJAX 请求,DOM 的操作或状态更新以及设置事件监听器。componentWillReceiveProps
:在初始化render
的时候不会执行,它会在组件接受到新的状态(Props)时被触发,一般用于父组件状态更新时子组件的重新渲染shouldComponentUpdate
:确定是否更新组件。默认情况下,它返回true
。如果确定在state
或props
更新后组件不需要在重新渲染,则可以返回false
,这是一个提高性能的方法。componentWillUpdate
:在shouldComponentUpdate
返回true
确定要更新组件之前件之前执行。componentDidUpdate
:它主要用于更新 DOM 以响应props
或state
更改。componentWillUnmount
:它用于取消任何的网络请求,或删除与组件关联的所有事件监听器。
React 组件生命周期有哪些不同阶段?
在组件生命周期中有四个不同的阶段:
Initialization:在这个阶段,组件准备设置初始化状态和默认属性。
Mounting:react 组件已经准备好挂载到浏览器 DOM 中。这个阶段包括
componentWillMount
和componentDidMount
生命周期方法。Updating:在这个阶段,组件以两种方式更新,发送新的 props 和 state 状态。此阶段包括
shouldComponentUpdate
、componentWillUpdate
和componentDidUpdate
生命周期方法。Unmounting:在这个阶段,组件已经不再被需要了,它从浏览器 DOM 中卸载下来。这个阶段包含
componentWillUnmount
生命周期方法。除以上四个常用生命周期外,还有一个错误处理的阶段:Error Handling:在这个阶段,不论在渲染的过程中,还是在生命周期方法中或是在任何子组件的构造函数中发生错误,该组件都会被调用。这个阶段包含了componentDidCatch
生命周期方法。
React 如何进行组件/逻辑复用?
抛开已经被官方弃用的 Mixin,组件抽象的技术目前有三种比较主流:
高阶组件:
属性代理
反向继承
渲染属性
react-hooks
Redux 中间件是怎么拿到 store 和 action? 然后怎么处理?
redux 中间件本质就是一个函数柯里化。redux applyMiddleware Api 源码中每个 middleware 接受 2 个参数, Store 的 getState 函数和 dispatch 函数,分别获得 store 和 action,最终返回一个函数。该函数会被传入 next 的下一个 middleware 的 dispatch 方法,并返回一个接收 action 的新函数,这个函数可以直接调用 next(action),或者在其他需要的时刻调用,甚至根本不去调用它。调用链中最后一个 middleware 会接受真实的 store 的 dispatch 方法作为 next 参数,并借此结束调用链。所以,middleware 的函数签名是({ getState,dispatch })=> next => action。
什么是 React Context?
Context
通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props
属性。
评论