关于react.js:前端必会react面试题合集

47次阅读

共计 9355 个字符,预计需要花费 24 分钟才能阅读完成。

调用 setState 之后产生了什么

在代码中调用 setState 函数之后,React 会将传入的参数与之前的状态进行合并,而后触发所谓的和谐过程(Reconciliation)。通过和谐过程,React 会以绝对高效的形式依据新的状态构建 React 元素树并且着手从新渲染整个 UI 界面。在 React 失去元素树之后,React 会计算出新的树和老的树之间的差别,而后依据差别对界面进行最小化从新渲染。通过 diff 算法,React 可能准确制导哪些地位产生了扭转以及应该如何扭转,这就保障了按需更新,而不是全副从新渲染。

  • 在 setState 的时候,React 会为以后节点创立一个 updateQueue 的更新列队。
  • 而后会触发 reconciliation 过程,在这个过程中,会应用名为 Fiber 的调度算法,开始生成新的 Fiber 树,Fiber 算法的最大特点是能够做到异步可中断的执行。
  • 而后 React Scheduler 会依据优先级高下,先执行优先级高的节点,具体是执行 doWork 办法。
  • 在 doWork 办法中,React 会执行一遍 updateQueue 中的办法,以取得新的节点。而后比照新旧节点,为老节点打上 更新、插入、替换 等 Tag。
  • 以后节点 doWork 实现后,会执行 performUnitOfWork 办法取得新节点,而后再反复下面的过程。
  • 当所有节点都 doWork 实现后,会触发 commitRoot 办法,React 进入 commit 阶段。
  • 在 commit 阶段中,React 会依据后面为各个节点打的 Tag,一次性更新整个 dom 元素

能够应用 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)

react 实现一个全局的 dialog

import React, {Component} from 'react';
import {is, fromJS} from 'immutable';
import ReactDOM from 'react-dom';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import './dialog.css';
let defaultState = {
  alertStatus:false,
  alertTip:"提醒",
  closeDialog:function(){},
  childs:''
}
class Dialog extends Component{
  state = {...defaultState};
  // css 动画组件设置为指标组件
  FirstChild = props => {const childrenArray = React.Children.toArray(props.children);
    return childrenArray[0] || null;
  }
  // 关上弹窗
  open =(options)=>{options = options || {};
    options.alertStatus = true;
    var props = options.props || {};
    var childs = this.renderChildren(props,options.childrens) || '';
    console.log(childs);
    this.setState({
      ...defaultState,
      ...options,
      childs
    })
  }
  // 敞开弹窗
  close(){this.state.closeDialog();
    this.setState({...defaultState})
  }
  renderChildren(props,childrens) {
    // 遍历所有子组件
    var childs = [];
    childrens = childrens || [];
    var ps = {
        ...props,  // 给子组件绑定 props
        _close:this.close  // 给子组件也绑定一个敞开弹窗的事件    
       };
    childrens.forEach((currentItem,index) => {
        childs.push(React.createElement(
            currentItem,
            {
                ...ps,
                key:index
            }
        ));
    })
    return childs;
  }
  shouldComponentUpdate(nextProps, nextState){return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
  }
   
  render(){
    return (
      <ReactCSSTransitionGroup
        component={this.FirstChild}
        transitionName='hide'
        transitionEnterTimeout={300}
        transitionLeaveTimeout={300}>
        <div className="dialog-con" style={this.state.alertStatus? {display:'block'}:{display:'none'}}>
            {this.state.childs}        </div>
      </ReactCSSTransitionGroup>
    );
  }
}
let div = document.createElement('div');
let props = { };
document.body.appendChild(div);
let Box = ReactD

子类:

// 子类 jsx
import React, {Component} from 'react';
class Child extends Component {constructor(props){super(props);
        this.state = {date: new Date()};
  }
  showValue=()=>{this.props.showValue && this.props.showValue()
  }
  render() {
    return (
      <div className="Child">
        <div className="content">
           Child           <button onClick={this.showValue}> 调用父的办法 </button>
        </div>
      </div>
    );
  }
}
export default Child;

css:

.dialog-con{
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.3);
}

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

在开发过程中,咱们须要保障某个元素的 key 在其同级元素中具备唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是早先创立的还是被挪动而来的元素,从而缩小不必要的元素重渲染。此外,React 还须要借助 Key 值来判断元素与本地状态的关联关系,因而咱们绝不可漠视转换函数中 Key 的重要性。

答:componentWillMount componentDidMount render

何为 redux

Redux 的根本思维是整个利用的 state 放弃在一个繁多的 store 中。store 就是一个简略的 javascript 对象,而扭转利用 state 的惟一形式是在利用中触发 actions,而后为这些 actions 编写 reducers 来批改 state。整个 state 转化是在 reducers 中实现,并且不应该有任何副作用。

指出 (组件) 生命周期办法的不同

  • componentWillMount — 多用于根组件中的应用程序配置
  • componentDidMount — 在这能够实现所有没有 DOM 就不能做的所有配置,并开始获取所有你须要的数据;如果须要设置事件监听,也能够在这实现
  • componentWillReceiveProps — 这个周期函数作用于特定的 prop 扭转导致的 state 转换
  • shouldComponentUpdate — 如果你放心组件适度渲染,shouldComponentUpdate 是一个改善性能的中央,因为如果组件接管了新的 prop,它能够阻止 (组件) 从新渲染。shouldComponentUpdate 应该返回一个布尔值来决定组件是否要从新渲染
  • componentWillUpdate — 很少应用。它能够用于代替组件的 componentWillReceivePropsshouldComponentUpdate(但不能拜访之前的 props)
  • componentDidUpdate — 罕用于更新 DOM,响应 prop 或 state 的扭转
  • componentWillUnmount — 在这你能够勾销网络申请,或者移除所有与组件相干的事件监听器

参考 前端进阶面试题具体解答

何为 reducer

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

React 中 refs 的作用是什么?有哪些利用场景?

Refs 提供了一种形式,用于拜访在 render 办法中创立的 React 元素或 DOM 节点。Refs 应该审慎应用,如下场景应用 Refs 比拟适宜:

  • 解决焦点、文本抉择或者媒体的管制
  • 触发必要的动画
  • 集成第三方 DOM 库

Refs 是应用 React.createRef() 办法创立的,他通过 ref 属性附加到 React 元素上。要在整个组件中应用 Refs,须要将 ref 在构造函数中调配给其实例属性:

class MyComponent extends React.Component {constructor(props) {super(props)
    this.myRef = React.createRef()}
  render() {return <div ref={this.myRef} />
  }
}

因为函数组件没有实例,因而不能在函数组件上间接应用 ref

function MyFunctionalComponent() {return <input />;}
class Parent extends React.Component {constructor(props) {super(props);
    this.textInput = React.createRef();}
  render() {
    // 这将不会工作!return (<MyFunctionalComponent ref={this.textInput} />
    );
  }
}

但能够通过闭合的帮忙在函数组件外部进行应用 Refs:

function CustomTextInput(props) {
  // 这里必须申明 textInput,这样 ref 回调才能够援用它
  let textInput = null;
  function handleClick() {textInput.focus();
  }
  return (
    <div>
      <input
        type="text"
        ref={(input) => {textInput = input;}} />      <input
        type="button"
        value="Focus the text input"
        onClick={handleClick}
      />
    </div>
  );  
}

留神:

  • 不应该适度的应用 Refs
  • ref 的返回值取决于节点的类型:

    • ref 属性被用于一个一般的 HTML 元素时,React.createRef() 将接管底层 DOM 元素作为他的 current 属性以创立 ref
    • ref 属性被用于一个自定义的类组件时,ref 对象将接管该组件已挂载的实例作为他的 current
  • 当在父组件中须要拜访子组件中的 ref 时可应用传递 Refs 或回调 Refs。

Component, Element, Instance 之间有什么区别和分割?

  • 元素: 一个元素 element 是一个一般对象 (plain object),形容了对于一个 DOM 节点或者其余组件component,你想让它在屏幕上出现成什么样子。元素element 能够在它的属性 props 中蕴含其余元素 (译注: 用于造成元素树)。创立一个 React 元素element 老本很低。元素 element 创立之后是不可变的。
  • 组件: 一个组件 component 能够通过多种形式申明。能够是带有一个 render() 办法的类,简略点也能够定义为一个函数。这两种状况下,它都把属性 props 作为输出,把返回的一棵元素树作为输入。
  • 实例: 一个实例 instance 是你在所写的组件类 component class 中应用关键字 this 所指向的货色(译注: 组件实例)。它用来存储本地状态和响应生命周期事件很有用。

函数式组件 (Functional component) 基本没有实例 instance。类组件(Class component) 有实例instance,然而永远也不须要间接创立一个组件的实例,因为 React 帮咱们做了这些。

在结构函数调用 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}
  }
}

react-router4 的外围

  • 路由变成了组件
  • 扩散到各个页面,不须要配置 比方<link> <route></route>

如何在 React 中应用 innerHTML

减少 dangerouslySetInnerHTML 属性,并且传入对象的属性名叫 \_html

function Component(props){return <div dangerouslySetInnerHTML={{_html:'<span> 你好 </span>'}}>
    </div>
}

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

展现组件关怀组件看起来是什么。展现专门通过 props 承受数据和回调,并且简直不会有本身的状态,但当展现组件领有本身的状态时,通常也只关怀 UI 状态而不是数据的状态。

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

为什么要应用 React. Children. map(props. children,()=>)而不是 props. children. map (() => )?

因为不能保障 props. children 将是一个数组。
以上面的代码为例。

<Parent>
    <h1> 有课前端网 </h1>
</Parent>

在父组件外部,如果尝试应用 props.children. map 映射子对象,则会抛出谬误,因为 props. children 是一个对象,而不是一个数组。
如果有多个子元素,React 会使 props.children 成为一个数组,如下所示。

<Parent>
  <h1> 有课前端网 </h1>
  <h2> 前端技术学习平台 </h2>
</Parent>;
// 不倡议应用如下形式,在这个案例中会抛出谬误。class Parent extends Component {render() {return <div> {this.props.children.map((obj) => obj)}</div>;
  }
}

倡议应用如下形式,防止在上一个案例中抛出谬误。

class Parent extends Component {render() {return <div> {React.Children.map(this.props.children, (obj) => obj)}</div>;
  }
}

vue 或者 react 优化整体优化

  1. 虚构 dom

为什么虚构 dom 会进步性能?(必考)

虚构 dom 相当于在 js 和实在 dom 两头加了一个缓存,利用 dom diff 算法防止了没有必要的 dom 操作,从而进步性能。

用 JavaScript 对象构造示意 DOM 树的构造;而后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,从新结构一棵新的对象树。而后用新的树和旧的树进行比拟,记录两棵树差别把 2 所记录的差别利用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。

React 的事件和一般的 HTML 事件有什么不同?

区别:

  • 对于事件名称命名形式,原生事件为全小写,react 事件采纳小驼峰;
  • 对于事件函数解决语法,原生事件为字符串,react 事件为函数;
  • react 事件不能采纳 return false 的形式来阻止浏览器的默认行为,而必须要地明确地调用 preventDefault() 来阻止默认行为。

合成事件是 react 模仿原生 DOM 事件所有能力的一个事件对象,其长处如下:

  • 兼容所有浏览器,更好的跨平台;
  • 将事件对立寄存在一个数组,防止频繁的新增与删除(垃圾回收)。
  • 不便 react 对立治理和事务机制。

事件的执行程序为原生事件先执行,合成事件后执行,合成事件会冒泡绑定到 document 上,所以尽量避免原生事件与合成事件混用,如果原生事件阻止冒泡,可能会导致合成事件不执行,因为须要冒泡到 document 上合成事件才会执行。

react 强制刷新

component.forceUpdate() 一个不罕用的生命周期办法, 它的作用就是强制刷新

官网解释如下

默认状况下,当组件的 state 或 props 发生变化时,组件将从新渲染。如果 render() 办法依赖于其余数据,则能够调用 forceUpdate() 强制让组件从新渲染。

调用 forceUpdate() 将以致组件调用 render() 办法,此操作会跳过该组件的 shouldComponentUpdate()。但其子组件会触发失常的生命周期办法,包含 shouldComponentUpdate() 办法。如果标记发生变化,React 仍将只更新 DOM。

通常你应该防止应用 forceUpdate(),尽量在 render() 中应用 this.props 和 this.state。

shouldComponentUpdate 在初始化 和 forceUpdate 不会执行

ssr 原理是什么?

外围原理其实就是借助虚构 DOM 来实现 react 代码可能在服务器运行的,node 外面能够执行 react 代码

diff 算法?

  • 把树形构造依照层级合成,只比拟同级元素
  • 给列表构造的每个单元增加惟一的 key 属性,不便比拟
  • React 只会匹配雷同 class 的 component(这外面的 class 指的是组件的名字)
  • 合并操作,调用 component 的 setState 办法的时候, React 将其标记为 dirty. 到每一个 事件循环完结, React 查看所有标记 dirty 的 component 从新绘制.
  • 抉择性子树渲染。开发人员能够重写 shouldComponentUpdate 进步 diff 的性能。

React 申明组件有哪几种办法,有什么不同?

React 申明组件的三种形式:

  • 函数式定义的 无状态组件
  • ES5 原生形式 React.createClass 定义的组件
  • ES6 模式的 extends React.Component 定义的组件

(1)无状态函数式组件 它是为了创立纯展现组件,这种组件只负责依据传入的 props 来展现,不波及到 state 状态的操作
组件不会被实例化,整体渲染性能失去晋升,不能拜访 this 对象,不能拜访生命周期的办法

(2)ES5 原生形式 React.createClass // RFC React.createClass 会自绑定函数办法,导致不必要的性能开销,减少代码过期的可能性。

(3)E6 继承模式 React.Component // RCC 目前极为举荐的创立有状态组件的形式,最终会取代 React.createClass 模式;绝对于 React.createClass 能够更好实现代码复用。

无状态组件绝对于于后者的区别: 与无状态组件相比,React.createClass 和 React.Component 都是创立有状态的组件,这些组件是要被实例化的,并且能够拜访组件的生命周期办法。

React.createClass 与 React.Component 区别:

① 函数 this 自绑定

  • React.createClass 创立的组件,其每一个成员函数的 this 都有 React 主动绑定,函数中的 this 会被正确设置。
  • React.Component 创立的组件,其成员函数不会主动绑定 this,须要开发者手动绑定,否则 this 不能获取以后组件实例对象。

② 组件属性类型 propTypes 及其默认 props 属性 defaultProps 配置不同

  • React.createClass 在创立组件时,无关组件 props 的属性类型及组件默认的属性会作为组件实例的属性来配置,其中 defaultProps 是应用 getDefaultProps 的办法来获取默认组件属性的
  • React.Component 在创立组件时配置这两个对应信息时,他们是作为组件类的属性,不是组件实例的属性,也就是所谓的类的动态属性来配置的。

③ 组件初始状态 state 的配置不同

  • React.createClass 创立的组件,其状态 state 是通过 getInitialState 办法来配置组件相干的状态;
  • React.Component 创立的组件,其状态 state 是在 constructor 中像初始化组件属性一样申明的。

正文完
 0