写点什么

react 面试应该准备哪些题目

作者:beifeng1996
  • 2022 年 9 月 26 日
    浙江
  • 本文字数:5636 字

    阅读完需:约 18 分钟

可以使用 TypeScript 写 React 应用吗?怎么操作?

(1)如果还未创建 Create React App 项目


  • 直接创建一个具有 typescript 的 Create React App 项目:


 npx create-react-app demo --typescript
复制代码


(2)如果已经创建了 Create React App 项目,需要将 typescript 引入到已有项目中


  • 通过命令将 typescript 引入项目:


npm install --save typescript @types/node @types/react @types/react-dom @types/jest
复制代码


  • 将项目中任何 后缀名为 ‘.js’ 的 JavaScript 文件重命名为 TypeScript 文件即后缀名为 ‘.tsx’(例如 src/index.js 重命名为 src/index.tsx )

在 ReactNative 中,如何解决 adb devices 找不到连接设备的问题?

在使用 Genymotion 时,首先需要在 SDK 的 platform-tools 中加入环境变量,然后在 Genymotion 中单击 Setting,选择 ADB 选项卡,单击 Use custom Android SDK tools,浏览本地 SDK 的位置,单击 OK 按钮就可以了。启动虛拟机后,在 cmd 中输入 adb devices 可以查看设备。


前端react面试题详细解答

在 React 中遍历的方法有哪些?

(1)遍历数组:map && forEach


import React from 'react';
class App extends React.Component { render() { let arr = ['a', 'b', 'c', 'd']; return ( <ul> { arr.map((item, index) => { return <li key={index}>{item}</li> }) } </ul> ) }}
class App extends React.Component { render() { let arr = ['a', 'b', 'c', 'd']; return ( <ul> { arr.forEach((item, index) => { return <li key={index}>{item}</li> }) } </ul> ) }}
复制代码


(2)遍历对象:map && for in


class App extends React.Component {  render() {    let obj = {      a: 1,      b: 2,      c: 3    }    return (      <ul>        {          (() => {            let domArr = [];            for(const key in obj) {              if(obj.hasOwnProperty(key)) {                const value = obj[key]                domArr.push(<li key={key}>{value}</li>)              }            }            return domArr;          })()        }      </ul>    )  }}
// Object.entries() 把对象转换成数组class App extends React.Component { render() { let obj = { a: 1, b: 2, c: 3 } return ( <ul> { Object.entries(obj).map(([key, value], index) => { // item是一个数组,把item解构,写法是[key, value] return <li key={key}>{value}</li> }) } </ul> ) }}
复制代码

高阶组件

高阶函数:如果一个函数接受一个或多个函数作为参数或者返回一个函数就可称之为高阶函数


高阶组件:如果一个函数 接受一个或多个组件作为参数并且返回一个组件 就可称之为 高阶组件


react 中的高阶组件


React 中的高阶组件主要有两种形式:属性代理反向继承


属性代理 Proxy


  • 操作 props

  • 抽离 state

  • 通过 ref 访问到组件实例

  • 用其他元素包裹传入的组件 WrappedComponent


反向继承


会发现其属性代理和反向继承的实现有些类似的地方,都是返回一个继承了某个父类的子类,只不过属性代理中继承的是 React.Component,反向继承中继承的是传入的组件 WrappedComponent


反向继承可以用来做什么:


1.操作 state


高阶组件中可以读取、编辑和删除WrappedComponent组件实例中的state。甚至可以增加更多的state项,但是非常不建议这么做因为这可能会导致state难以维护及管理。


function withLogging(WrappedComponent) {        return class extends WrappedComponent {            render() {                return (                    <div>;                        <h2>;Debugger Component Logging...<h2>;                        <p>;state:<p>;                        <pre>;{JSON.stringify(this.state, null, 4)}<pre>;                        <p>props:<p>;                        <pre>{JSON.stringify(this.props, null, 4)}<pre>;                        {super.render()}                    <div>;                );            }        };    }
复制代码


2.渲染劫持(Render Highjacking)


条件渲染通过 props.isLoading 这个条件来判断渲染哪个组件。


修改由 render() 输出的 React 元素树

Redux Thunk 的作用是什么

Redux thunk 是一个允许你编写返回一个函数而不是一个 action 的 actions creators 的中间件。如果满足某个条件,thunk 则可以用来延迟 action 的派发(dispatch),这可以处理异步 action 的派发(dispatch)。

diff 算法如何比较?

  • 只对同级比较,跨层级的 dom 不会进行复用

  • 不同类型节点生成的 dom 树不同,此时会直接销毁老节点及子孙节点,并新建节点

  • 可以通过 key 来对元素 diff 的过程提供复用的线索

  • 单节点 diff

  • 单点 diff 有如下几种情况:

  • key 和 type 相同表示可以复用节点

  • key 不同直接标记删除节点,然后新建节点

  • key 相同 type 不同,标记删除该节点和兄弟节点,然后新创建节点

在 Redux 中使用 Action 要注意哪些问题?

在 Redux 中使用 Action 的时候, Action 文件里尽量保持 Action 文件的纯净,传入什么数据就返回什么数据,最妤把请求的数据和 Action 方法分离开,以保持 Action 的纯净。

为什么 React 要用 JSX?

JSX 是一个 JavaScript 的语法扩展,或者说是一个类似于 XML 的 ECMAScript 语法扩展。它本身没有太多的语法定义,也不期望引入更多的标准。


其实 React 本身并不强制使用 JSX。在没有 JSX 的时候,React 实现一个组件依赖于使用 React.createElement 函数。代码如下:


class Hello extends React.Component {  render() {    return React.createElement(        'div',        null,         `Hello ${this.props.toWhat}`      );  }}ReactDOM.render(  React.createElement(Hello, {toWhat: 'World'}, null),  document.getElementById('root'));
复制代码


而 JSX 更像是一种语法糖,通过类似 XML 的描述方式,描写函数对象。在采用 JSX 之后,这段代码会这样写:


class Hello extends React.Component {  render() {    return <div>Hello {this.props.toWhat}</div>;  }}ReactDOM.render(  <Hello toWhat="World" />,  document.getElementById('root'));
复制代码


通过对比,可以清晰地发现,代码变得更为简洁,而且代码结构层次更为清晰。


因为 React 需要将组件转化为虚拟 DOM 树,所以在编写代码时,实际上是在手写一棵结构树。而 XML 在树结构的描述上天生具有可读性强的优势。


但这样可读性强的代码仅仅是给写程序的同学看的,实际上在运行的时候,会使用 Babel 插件将 JSX 语法的代码还原为 React.createElement 的代码。


总结: JSX 是一个 JavaScript 的语法扩展,结构类似 XML。JSX 主要用于声明 React 元素,但 React 中并不强制使用 JSX。即使使用了 JSX,也会在构建过程中,通过 Babel 插件编译为 React.createElement。所以 JSX 更像是 React.createElement 的一种语法糖。


React 团队并不想引入 JavaScript 本身以外的开发体系。而是希望通过合理的关注点分离保持组件开发的纯粹性。

shouldComponentUpdate 的作用

shouldComponentUpdate 允许我们手动地判断是否要进行组件更新,根据组件的应用场景设置函数的合理返回值能够帮我们避免不必要的更新

请说岀 React 从 EMAScript5 编程规范到 EMAScript6 编程规范过程中的几点改变。

主要改变如下。(1)创建组件的方法不同。EMAScript5 版本中,定义组件用 React.createClass。EMAScript6 版本中,定义组件要定义组件类,并继承 Component 类。(2)定义默认属性的方法不同。EMAScript5 版本中,用 getDefaultProps 定义默认属性。EMAScript6 版本中,为组件定义 defaultProps 静态属性,来定义默认属性。(3)定义初始化状态的方法不同。EMAScript5 版本中,用 getInitialState 定义初始化状态。EMAScript6 版本中,在构造函数中,通过 this. state 定义初始化状态。注意:构造函数的第一个参数是属性数据,一定要用 super 继承。(4)定义属性约束的方法不同。EMAScript5 版本中,用 propTypes 定义属性的约束。EMAScript6 版本中,为组件定义 propsTypes 静态属性,来对属性进行约束。(5)使用混合对象、混合类的方法不同。EMAScript5 版本中,通过 mixins 继承混合对象的方法。EMAScript6 版本中,定义混合类,让混合类继承 Component 类,然后让组件类继承混合类,实现对混合类方法的继承。(6)绑定事件的方法不同。EMAScript5 版本中,绑定的事件回调函数作用域是组件实例化对象。EMAScript6 版本中,绑定的事件回调函数作用域是 null。(7)父组件传递方法的作用域不同。EMAScript5 版本中,作用域是父组件。 EMAScript6 版本中,变成了 null。(8)组件方法作用域的修改方法不同。EMAScript5 版本中,无法改变作用域。EMAScript6 版本中,作用域是可以改变的。

如何用 React 构建( build)生产模式?

通常,使用 Webpack 的 DefinePlugin 方法将 NODE ENV 设置为 production。这将剥离 propType 验证和额外的警告。除此之外,还可以减少代码,因为 React 使用 Uglify 的 dead-code 来消除开发代码和注释,这将大大减少包占用的空间。

展示组件(Presentational component)和容器组件(Container component)之间有何不同

展示组件关心组件看起来是什么。展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态。


容器组件则更关心组件是如何运作的。容器组件会为展示组件或者其它容器组件提供数据和行为(behavior),它们会调用 Flux actions,并将其作为回调提供给展示组件。容器组件经常是有状态的,因为它们是(其它组件的)数据源。

使用状态要注意哪些事情?

要注意以下几点。


  • 不要直接更新状态

  • 状态更新可能是异步的

  • 状态更新要合并。

  • 数据从上向下流动

react 代理原生事件为什么?

通过冒泡实现,为了统一管理,对更多浏览器有兼容效果


合成事件原理


如果 react 事件绑定在了真实 DOM 节点上,一个节点同事有多个事件时,页面的响应和内存的占用会受到很大的影响。因此 SyntheticEvent 作为中间层出现了。


事件没有在目标对象上绑定,而是在 document 上监听所支持的所有事件,当事件发生并冒泡至 document 时,react 将事件内容封装并叫由真正的处理函数运行。


版权声明:本文为 CSDN 博主「jiuwanli666」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

react 的全家桶有哪些

  • react:核心

  • redux:相当于数据,主要存储数据状态

  • react-redux 可以完成数据订阅

  • redux-thunk 可以实现异步的 action

  • redux-logger 是 redux 的日志中间件

  • react-router 专门为 react 提供路由解决方案,它利用 HTML5 的 history API,来操作浏览器的 session history (会话历史)

  • react-router:提供核心的路由组件与函数

  • react-router-config:用来配置静态路由(还在开发中)

  • react-router-native:

  • react-router-dom:

  • axios:是基于 promise 的用于浏览器和服务端进行数据交互的技术

  • antd:Ant Degisn 是个很好的 React UI 库

根据下面定义的代码,可以找出存在的两个问题吗 ?

请看下面的代码:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uT8bsRru-1664149050165)(https://segmentfault.com/img/bVbzUKg "图片描述")]答案:1.在构造函数没有将 props 传递给 super,它应该包括以下行


constructor(props) {super(props);// ...}
复制代码


2.事件监听器(通过addEventListener()分配时)的作用域不正确,因为 ES6 不提供自动绑定。因此,开发人员可以在构造函数中重新分配clickHandler来包含正确的绑定:


constructor(props) {super(props);this.clickHandler = this.clickHandler.bind(this);// ...}
复制代码

constructor 为什么不先渲染?

由 ES6 的继承规则得知,不管子类写不写 constructor,在 new 实例的过程都会给补上 constructor。


所以:constructor 钩子函数并不是不可缺少的,子组件可以在一些情况略去。比如不自己的 state,从 props 中获取的情况

React 中的高阶组件运用了什么设计模式?

使用了装饰模式,高阶组件的运用:


function withWindowWidth(BaseComponent) {  class DerivedClass extends React.Component {    state = {      windowWidth: window.innerWidth,    }    onResize = () => {      this.setState({        windowWidth: window.innerWidth,      })    }    componentDidMount() {      window.addEventListener('resize', this.onResize)    }    componentWillUnmount() {      window.removeEventListener('resize', this.onResize);    }    render() {      return <BaseComponent {...this.props} {...this.state}/>    }  }  return DerivedClass;}const MyComponent = (props) => {  return <div>Window width is: {props.windowWidth}</div>};export default withWindowWidth(MyComponent);
复制代码


装饰模式的特点是不需要改变 被装饰对象 本身,而只是在外面套一个外壳接口。JavaScript 目前已经有了原生装饰器的提案,其用法如下:


@testable   class MyTestableClass {}
复制代码

何为 reducer

一个 reducer 是一个纯函数,该函数以先前的 state 和一个 action 作为参数,并返回下一个 state。

class 类的 key 改了,会发生什么,会执行哪些周期函数?

在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。


答:componentWillMount componentDidMount render

用户头像

beifeng1996

关注

还未添加个人签名 2022.09.01 加入

还未添加个人简介

评论

发布
暂无评论
react面试应该准备哪些题目_前端_beifeng1996_InfoQ写作社区