乐趣区

关于前端:美团前端常见react面试题附答案

你对 Time Slice 的了解?

工夫分片

  • React 在渲染(render)的时候,不会阻塞当初的线程
  • 如果你的设施足够快,你会感觉渲染是同步的
  • 如果你设施十分慢,你会感觉还算是灵活的
  • 尽管是异步渲染,然而你将会看到残缺的渲染,而不是一个组件一行行的渲染进去
  • 同样书写组件的形式

也就是说,这是 React 背地在做的事件,对于咱们开发者来说,是通明的,具体是什么样的成果呢?

React- Router 有几种模式?

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

和谐阶段 setState 外部干了什么

  • 当调用 setState 时,React 会做的第一件事件是将传递给 setState 的对象合并到组件的以后状态
  • 这将启动一个称为和解(reconciliation)的过程。和解(reconciliation)的最终目标是以最无效的形式,依据这个新的状态来更新 UI。为此,React 将构建一个新的 React 元素树(您能够将其视为 UI 的对象示意)
  • 一旦有了这个树,为了弄清 UI 如何响应新的状态而扭转,React 会将这个新树与上一个元素树相比拟(diff)

通过这样做,React 将会晓得产生的确切变动,并且通过理解产生什么变动,只需在相对必要的状况下进行更新即可最小化 UI 的占用空间

为什么虚构 dom 会进步性能

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

具体实现步骤如下:

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

setState 办法的第二个参数有什么用?应用它的目标是什么?

它是一个回调函数,当 setState 办法执行完结并从新渲染该组件时调用它。在工作中,更好的形式是应用 React 组件生命周期之——“存在期”的生命周期办法,而不是依赖这个回调函数。

export class App extends Component {constructor(props) {super(props);
    this.state = {username: "雨夜清荷",};
  }
  render() {return <div> {this.state.username}</div>;
  }
  componentDidMount() {
    this.setstate(
      {username: "有课前端网",},
      () => console.log("re-rendered success.")
    );
  }
}

React Portal 有哪些应用场景

  • 在以前,react 中所有的组件都会位于 #app 下,而应用 Portals 提供了一种脱离 #app 的组件
  • 因而 Portals 适宜脱离文档流(out of flow) 的组件,特地是 position: absolute 与 position: fixed 的组件。比方模态框,告诉,正告,goTop 等。

以下是官网一个模态框的示例,能够在以下地址中测试成果

<html>
  <body>
    <div id="app"></div>
    <div id="modal"></div>
    <div id="gotop"></div>
    <div id="alert"></div>
  </body>
</html>
const modalRoot = document.getElementById('modal');

class Modal extends React.Component {constructor(props) {super(props);
    this.el = document.createElement('div');
  }

  componentDidMount() {modalRoot.appendChild(this.el);
  }

  componentWillUnmount() {modalRoot.removeChild(this.el);
  }

  render() {
    return ReactDOM.createPortal(
      this.props.children,
      this.el,
    );
  }
}

React Hooks 当中的 useEffect 是如何辨别生命周期钩子的

useEffect 能够看成是 componentDidMountcomponentDidUpdatecomponentWillUnmount三者的联合。useEffect(callback,)接管两个参数,调用形式如下

useEffect(() => {console.log('mounted');

   return () => {console.log('willUnmount');
   }
 }, );

生命周期函数的调用次要是通过第二个参数来进行管制,有如下几种状况:

  • 参数不传时,则每次都会优先调用上次保留的函数中返回的那个函数,而后再调用内部那个函数;
  • 参数传 [] 时,则内部的函数只会在初始化时调用一次,返回的那个函数也只会最终在组件卸载时调用一次;
  • 参数有值时,则只会监听到数组中的值发生变化后才优先调用返回的那个函数,再调用内部的函数。

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

Redux 中间件原理

  • 指的是 action 和 store 之间,沟通的桥梁就是 dispatch,action 就是个对象。比方你用了 redux-thunk,action 也能够是个函数,怎么实现这个过程,就是通过中间件这个桥梁帮你实现的。action 达到 store 之前会走中间件,这个中间件会把函数式的 action 转化为一个对象,在传递给 store

react 性能优化是哪个周期函数

shouldComponentUpdate 这个办法用来判断是否须要调用 render 办法从新描述 dom。因为 dom 的描述十分耗费性能,如果咱们能在 shouldComponentUpdate 方 法中可能写出更优化的 dom diff 算法,能够极大的进步性能

组件是什么?类是什么?类变编译成什么

  • 组件指的是页面的一部分,实质就是一个类,最实质就是一个构造函数
  • 类编译成构造函数

react 中的 Portal 是什么?

Portals 提供了一种很好的将子节点渲染到父组件以外的 DOM 节点的形式。
第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或碎片。
第二个参数(container)则是一个 DOM 元素。

ReactDOM.createPortal(child, container)

高阶组件

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

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

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 元素树

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

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

shouldComponentUpdate 的作用

shouldComponentUpdate 容许咱们手动地判断是否要进行组件更新,依据组件的利用场景设置函数的正当返回值可能帮咱们防止不必要的更新

对虚构 DOM 的了解?虚构 DOM 次要做了什么?虚构 DOM 自身是什么?

从实质上来说,Virtual Dom 是一个 JavaScript 对象,通过对象的形式来示意 DOM 构造。将页面的状态形象为 JS 对象的模式,配合不同的渲染工具,使跨平台渲染成为可能。通过事务处理机制,将屡次 DOM 批改的后果一次性的更新到页面上,从而无效的缩小页面渲染的次数,缩小批改 DOM 的重绘重排次数,进步渲染性能。

虚构 DOM 是对 DOM 的形象,这个对象是更加轻量级的对 DOM 的形容。它设计的最后目标,就是更好的跨平台,比方 node.js 就没有 DOM,如果想实现 SSR,那么一个形式就是借助虚构 dom,因为虚构 dom 自身是 js 对象。在代码渲染到页面之前,vue 或者 react 会把代码转换成一个对象(虚构 DOM)。以对象的模式来形容实在 dom 构造,最终渲染到页面。在每次数据发生变化前,虚构 dom 都会缓存一份,变动之时,当初的虚构 dom 会与缓存的虚构 dom 进行比拟。在 vue 或者 react 外部封装了 diff 算法,通过这个算法来进行比拟,渲染时批改扭转的变动,原先没有产生扭转的通过原先的数据进行渲染。

另外古代前端框架的一个根本要求就是毋庸手动操作 DOM,一方面是因为手动操作 DOM 无奈保障程序性能,多人合作的我的项目中如果 review 不严格,可能会有开发者写出性能较低的代码,另一方面更重要的是省略手动 DOM 操作能够大大提高开发效率。

为什么要用 Virtual DOM:

(1)保障性能上限,在不进行手动优化的状况下,提供过得去的性能

上面比照一下批改 DOM 时实在 DOM 操作和 Virtual DOM 的过程,来看一下它们重排重绘的性能耗费∶

  • 实在 DOM∶ 生成 HTML 字符串+ 重建所有的 DOM 元素
  • Virtual DOM∶ 生成 vNode+ DOMDiff+必要的 DOM 更新

Virtual DOM 的更新 DOM 的筹备工作消耗更多的工夫,也就是 JS 层面,相比于更多的 DOM 操作它的生产是极其便宜的。尤雨溪在社区论坛中说道∶ 框架给你的保障是,你不须要手动优化的状况下,我仍然能够给你提供过得去的性能。(2)跨平台 Virtual DOM 实质上是 JavaScript 的对象,它能够很不便的跨平台操作,比方服务端渲染、uniapp 等。

React 中 constructor 和 getInitialState 的区别?

两者都是用来初始化 state 的。前者是 ES6 中的语法,后者是 ES5 中的语法,新版本的 React 中曾经废除了该办法。

getInitialState 是 ES5 中的办法,如果应用 createClass 办法创立一个 Component 组件,能够主动调用它的 getInitialState 办法来获取初始化的 State 对象,

var APP = React.creatClass ({getInitialState() {
    return { 
        userName: 'hi',
        userId: 0
     };
 }
})

React 在 ES6 的实现中去掉了 getInitialState 这个 hook 函数,规定 state 在 constructor 中实现,如下:

Class App extends React.Component{constructor(props){super(props);
      this.state={};}
  }

怎么用 React.createElement 重写上面的代码

Question:

const element = (
  <h1 className="greeting">
    Hello, rdhub.cn!
  </h1>
);

Answer:

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, rdhub.cn!'
);

在 React 中,何为 state

State 和 props 相似,但它是公有的,并且齐全由组件本身管制。State 实质上是一个持有数据,并决定组件如何渲染的对象。

react 旧版生命周期函数

初始化阶段

  • getDefaultProps: 获取实例的默认属性
  • getInitialState: 获取每个实例的初始化状态
  • componentWillMount:组件行将被装载、渲染到页面上
  • render: 组件在这里生成虚构的 DOM 节点
  • componentDidMount: 组件真正在被装载之后

运行中状态

  • componentWillReceiveProps: 组件将要接管到属性的时候调用
  • shouldComponentUpdate: 组件承受到新属性或者新状态的时候(能够返回 false,接收数据后不更新,阻止 render 调用,前面的函数不会被继续执行了)
  • componentWillUpdate: 组件行将更新不能批改属性和状态
  • render: 组件从新描述
  • componentDidUpdate: 组件曾经更新

销毁阶段

  • componentWillUnmount: 组件行将销毁

为什么应用 jsx 的组件中没有看到应用 react 却须要引入 react?

实质上来说 JSX 是 React.createElement(component, props, ...children) 办法的语法糖。在 React 17 之前,如果应用了 JSX,其实就是在应用 React,babel 会把组件转换为 CreateElement 模式。在 React 17 之后,就不再须要引入,因为 babel 曾经能够帮咱们主动引入 react。

什么是 React Context?

Context 通过组件树提供了一个传递数据的办法,从而防止了在每一个层级手动的传递 props 属性。

退出移动版