乐趣区

关于react.js:react面试题笔记整理

componentWillReceiveProps 调用机会

  • 曾经被废除掉
  • 当 props 扭转的时候才调用,子组件第二次接管到 props 的时候

在调用 setState 之后产生了什么

  • 状态合并,触发和谐:

    setState 函数之后,会将传入的参数对象与以后的状态合并,而后登程调用过程

  • 依据新的状态构建虚构 dom 树

    通过和谐过程,react 会高效的依据新的状态构建虚构 DOM 树,筹备渲染整个 UI 页面

  • 计算新老树节点差别,最小化渲染

    得倒新的虚构 DOM 树后,会计算出新老树的节点差别,会依据差别对界面进行最小化渲染

  • 按需更新

    在差别话计算中,react 能够绝对精确的晓得哪些地位产生了扭转以及该如何扭转,这保障按需更新,而不是发表从新渲染

概述一下 React 中的事件处理逻辑。

为了解决跨浏览器兼容性问题,React 会将浏览器原生事件(Browser Native Event)封装为合成事件(Synthetic Event)并传入设置的事件处理程序中。
这里的合成事件提供了与原生事件雷同的接口,不过它们屏蔽了底层浏览器的细节差别,保障了行为的一致性。另外,React 并没有间接将事件附着到子元素上,而是以繁多事件监听器的形式将所有的事件发送到顶层进行解决(基于事件委托原理)。
这样 React 在更新 DOM 时就不须要思考如何解决附着在 DOM 上的事件监听器,最终达到优化性能的目标。

在 React 中元素(element)和组件(component)有什么区别?

简略地说,在 React 中元素(虛拟 DOM)形容了你在屏幕上看到的 DOM 元素。
换个说法就是,在 React 中元素是页面中 DOM 元素的对象示意形式。在 React 中组件是一个函数或一个类,它能够承受输出并返回一个元素。
留神:工作中,为了进步开发效率,通常应用 JSX 语法示意 React 元素(虚构 DOM)。在编译的时候,把它转化成一个 React. createElement 调用办法。

参考:前端 react 面试题具体解答

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

在应用 Genymotion 时,首先须要在 SDK 的 platform-tools 中退出环境变量,而后在 Genymotion 中单击 Setting,抉择 ADB 选项卡,单击 Use custom Android SDK tools,浏览本地 SDK 的地位,单击 OK 按钮就能够了。启动虛拟机后,在 cmd 中输出 adb devices 能够查看设施。

说说 React 组件开发中对于作用域的常见问题。

在 EMAScript5 语法标准中,对于作用域的常见问题如下。
(1)在 map 等办法的回调函数中,要绑定作用域 this(通过 bind 办法)。
(2)父组件传递给子组件办法的作用域是父组件实例化对象,无奈扭转。
(3)组件事件回调函数办法的作用域是组件实例化对象(绑定父组件提供的办法就是父组件实例化对象),无奈扭转。
在 EMAScript6 语法标准中,对于作用域的常见问题如下。
(1)当应用箭头函数作为 map 等办法的回调函数时,箭头函数的作用域是以后组件的实例化对象(即箭头函数的作用域是定义时的作用域),毋庸绑定作用域。
(2)事件回调函数要绑定组件作用域。
(3)父组件传递办法要绑定父组件作用域。
总之,在 EMAScript6 语法标准中,组件办法的作用域是能够扭转的。

生命周期调用办法的程序是什么?

React 生命周期分为三大周期,11 个阶段,生命周期办法调用程序别离如下。
(1)在创立期的五大阶段,调用办法的程序如下。

  • getDetaultProps:定义默认属性数据。
  • getInitialState:初始化默认状态数据。
  • component WillMount:组件行将被构建。
  • render:渲染组件。
  • componentDidMount:组件构建实现

(2)在存在期的五大阶段,调用办法的程序如下。

  • componentWillReceiveProps:组件行将接管新的属性数据。
  • shouldComponentUpdate:判断组件是否应该更新。
  • componnent WillUpdate:组件行将更新。
  • render:渲染组件。
  • componentDidUpdate:组件更新实现。

(3)在销毁期的一个阶段,调用办法 componentWillUnmount,示意组件行将被销毀。

React 中 refs 的作用是什么

  • RefsReact 提供给咱们的平安拜访 DOM元素或者某个组件实例的句柄
  • 能够为元素增加 ref 属性而后在回调函数中承受该元素在 DOM 树中的句柄,该值会作为回调函数的第一个参数返回

React- Router 有几种模式?

有以下几种模式。
HashRouter,通过散列实现,路由要带 #。
BrowerRouter,利用 HTML5 中 history API 实现,须要服务器端反对,兼容性不是很好。

在 React 中如何处理事件

为了解决跨浏览器的兼容性问题,SyntheticEvent 实例将被传递给你的事件处理函数,SyntheticEvent是 React 跨浏览器的浏览器原生事件包装器,它还领有和浏览器原生事件雷同的接口,包含 stopPropagation()preventDefault()
比拟乏味的是,React 实际上并不将事件附加到子节点自身。React 应用单个事件侦听器侦听顶层的所有事件。这对性能有益处,也意味着 React 在更新 DOM 时不须要跟踪事件监听器。

受控组件和非受控组件区别是啥?

  • 受控组件 是 React 管制中的组件,并且是表单数据实在的惟一起源。
  • 非受控组件是由 DOM 解决表单数据的中央,而不是在 React 组件中。
    只管非受控组件通常更易于实现,因为只需应用 refs 即可从 DOM 中获取值,但通常倡议优先选择受管制的组件,而不是非受管制的组件。
    这样做的次要起因是受控组件反对即时字段验证,容许有条件地禁用 / 启用按钮,强制输出格局。

redux 有什么毛病

  • 一个组件所须要的数据,必须由父组件传过来,而不能像 flux 中间接从 store 取。
  • 当一个组件相干数据更新时,即便父组件不须要用到这个组件,父组件还是会从新 render,可能会有效率影响,或者须要写简单的shouldComponentUpdate 进行判断。

在应用 React Router 时,如何获取以后页面的路由或浏览器中地址栏中的地址?

在以后组件的 props 中,蕴含 location 属性对象,蕴含以后页面路由地址信息,在 match 中存储以后路由的参数等数据信息。能够间接通过 this .props 应用它们。

在结构函数调用 super 并将 props 作为参数传入的作用是啥?

在调用 super() 办法之前,子类构造函数无奈应用 this 援用,ES6 子类也是如此。将 props 参数传递给 super() 调用的次要起因是在子构造函数中可能通过 this.props 来获取传入的 props
传递 props

class MyComponent extends React.Component {constructor(props) {super(props);
    console.log(this.props); // {name: 'sudheer',age: 30}
  }
}

没传递 props

class MyComponent extends React.Component {constructor(props) {super();
    console.log(this.props); // undefined
    // 然而 Props 参数依然可用
    console.log(props); // Prints {name: 'sudheer',age: 30}
  }
  render() {
    // 构造函数内部不受影响
    console.log(this.props); // {name: 'sudheer',age: 30}
  }
}

下面示例揭示了一点。props 的行为只有在构造函数中是不同的,在构造函数之外也是一样的。

useEffect(fn, []) 和 componentDidMount 有什么差别

useEffect 会捕捉 props 和 state。所以即使在回调函数里,你拿到的还是初始的 props 和 state。如果想得到“最新”的值,能够应用 ref。

React 有哪些优化性能的伎俩

类组件中的优化伎俩

  • 应用纯组件 PureComponent 作为基类。
  • 应用 React.memo 高阶函数包装组件。
  • 应用 shouldComponentUpdate 生命周期函数来自定义渲染逻辑。

办法组件中的优化伎俩

  • 应用 useMemo
  • 应用 useCallBack

其余形式

  • 在列表须要频繁变动时,应用惟一 id 作为 key,而不是数组下标。
  • 必要时通过扭转 CSS 款式暗藏显示组件,而不是通过条件判断显示暗藏组件。
  • 应用 Suspense 和 lazy 进行懒加载,例如:
import React, {lazy, Suspense} from "react";

export default class CallingLazyComponents extends React.Component {render() {
    var ComponentToLazyLoad = null;

    if (this.props.name == "Mayank") {ComponentToLazyLoad = lazy(() => import("./mayankComponent"));
    } else if (this.props.name == "Anshul") {ComponentToLazyLoad = lazy(() => import("./anshulComponent"));
    }

    return (
      <div>
        <h1>This is the Base User: {this.state.name}</h1>
        <Suspense fallback={<div>Loading...</div>}>
          <ComponentToLazyLoad />
        </Suspense>
      </div>
    )
  }
}

新版生命周期

在新版本中,React 官网对生命周期有了新的 变动倡议:

  • 应用 getDerivedStateFromProps 替换componentWillMount;
  • 应用 getSnapshotBeforeUpdate 替换componentWillUpdate;
  • 防止应用componentWillReceiveProps

其实该变动的起因,正是因为上述提到的 Fiber。首先,从下面咱们晓得 React 能够分成 reconciliationcommit两个阶段,对应的生命周期如下:

reconciliation

  • componentWillMount
  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate

commit

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

Fiber 中,reconciliation 阶段进行了工作宰割,波及到 暂停 和 重启,因而可能会导致 reconciliation 中的生命周期函数在一次更新渲染循环中被 屡次调用 的状况,产生一些意外谬误

新版的倡议生命周期如下:

class Component extends React.Component {
  // 替换 `componentWillReceiveProps`,// 初始化和 update 时被调用
  // 动态函数,无奈应用 this
  static getDerivedStateFromProps(nextProps, prevState) {}

  // 判断是否须要更新组件
  // 能够用于组件性能优化
  shouldComponentUpdate(nextProps, nextState) {}

  // 组件被挂载后触发
  componentDidMount() {}

  // 替换 componentWillUpdate
  // 能够在更新之前获取最新 dom 数据
  getSnapshotBeforeUpdate() {}

  // 组件更新后调用
  componentDidUpdate() {}

  // 组件行将销毁
  componentWillUnmount() {}

  // 组件已销毁
  componentDidUnMount() {}
}

应用倡议:

  • constructor 初始化 state
  • componentDidMount 中进行事件监听,并在 componentWillUnmount 中解绑事件;
  • componentDidMount 中进行数据的申请,而不是在componentWillMount
  • 须要依据 props 更新 state 时,应用getDerivedStateFromProps(nextProps, prevState)

    • 旧 props 须要本人存储,以便比拟;
public static getDerivedStateFromProps(nextProps, prevState) {
    // 当新 props 中的 data 发生变化时,同步更新到 state 上
    if (nextProps.data !== prevState.data) {
        return {data: nextProps.data}
    } else {return null1}
}

能够在 componentDidUpdate 监听 props 或者 state 的变动,例如:

componentDidUpdate(prevProps) {
    // 当 id 发生变化时,从新获取数据
    if (this.props.id !== prevProps.id) {this.fetchData(this.props.id);
    }
}
  • 在 componentDidUpdate 应用 setState 时,必须加条件,否则将进入死循环;
  • getSnapshotBeforeUpdate(prevProps, prevState)能够在更新之前获取最新的渲染数据,它的调用是在 render 之后,update 之前;
  • shouldComponentUpdate: 默认每次调用 setState,肯定会最终走到 diff 阶段,但能够通过 shouldComponentUpdate 的生命钩子返回 false 来间接阻止前面的逻辑执行,通常是用于做条件渲染,优化渲染的性能。

类组件和函数组件之间的区别是啥?

  • 类组件 能够应用其余个性,如状态 state 和生命周期钩子。
  • 当组件只是接管 props 渲染到页面时,就是无状态组件,就属于函数组件,也被称为哑组件或展现组件。
    函数组件和类组件当然是有区别的,而且函数组件的性能比类组件的性能要高,因为类组件应用的时候要实例化,而函数组件间接执行函数取返回后果即可。为了进步性能,尽量应用函数组件。

    区别 函数组件 类组件
    是否有 this 没有
    是否有生命周期 没有
    是否有状态 state 没有

依据上面定义的代码,能够找出存在的两个问题吗?

请看上面的代码:

答案:
1. 在构造函数没有将 props 传递给 super,它应该包含以下行

constructor(props) {super(props);
// ...
}

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

constructor(props) {super(props);
this.clickHandler = this.clickHandler.bind(this);
// ...
}

redux 中间件

中间件提供第三方插件的模式,自定义拦挡 action -> reducer 的过程。变为 action -> middlewares -> reducer。这种机制能够让咱们扭转数据流,实现如异步actionaction 过滤,日志输入,异样报告等性能

  • redux-logger:提供日志输入
  • redux-thunk:解决异步操作
  • redux-promise:解决异步操作,actionCreator的返回值是promise
退出移动版