关于react.js:百度前端必会react面试题总结

8次阅读

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

对 React 和 Vue 的了解,它们的异同

相似之处:

  • 都将注意力集中放弃在外围库,而将其余性能如路由和全局状态治理交给相干的库
  • 都有本人的构建工具,能让你失去一个依据最佳实际设置的我的项目模板。
  • 都应用了 Virtual DOM(虚构 DOM)进步重绘性能
  • 都有 props 的概念,容许组件间的数据传递
  • 都激励组件化利用,将利用分拆成一个个性能明确的模块,进步复用性

不同之处:

1)数据流

Vue 默认反对数据双向绑定,而 React 始终提倡单向数据流

2)虚构 DOM

Vue2.x 开始引入 ”Virtual DOM”,打消了和 React 在这方面的差别,然而在具体的细节还是有各自的特点。

  • Vue 声称能够更快地计算出 Virtual DOM 的差别,这是因为它在渲染过程中,会跟踪每一个组件的依赖关系,不须要从新渲染整个组件树。
  • 对于 React 而言,每当利用的状态被扭转时,全副子组件都会从新渲染。当然,这能够通过 PureComponent/shouldComponentUpdate 这个生命周期办法来进行管制,但 Vue 将此视为默认的优化。

3)组件化

React 与 Vue 最大的不同是模板的编写。

  • Vue 激励写近似惯例 HTML 的模板。写起来很靠近规范 HTML 元素,只是多了一些属性。
  • React 举荐你所有的模板通用 JavaScript 的语法扩大——JSX 书写。

具体来讲:React 中 render 函数是反对闭包个性的,所以咱们 import 的组件在 render 中能够间接调用。然而在 Vue 中,因为模板中应用的数据都必须挂在 this 上进行一次直达,所以 import 完组件之后,还须要在 components 中再申明下。

4)监听数据变动的实现原理不同

  • Vue 通过 getter/setter 以及一些函数的劫持,能准确晓得数据变动,不须要特地的优化就能达到很好的性能
  • React 默认是通过比拟援用的形式进行的,如果不优化(PureComponent/shouldComponentUpdate)可能导致大量不必要的 vDOM 的从新渲染。这是因为 Vue 应用的是可变数据,而 React 更强调数据的不可变。

5)高阶组件

react 能够通过高阶组件(Higher Order Components– HOC)来扩大,而 vue 须要通过 mixins 来扩大。

起因高阶组件就是高阶函数,而 React 的组件自身就是纯正的函数,所以高阶函数对 React 来说大海捞针。相同 Vue.js 应用 HTML 模板创立视图组件,这时模板无奈无效的编译,因而 Vue 不采纳 HOC 来实现。

6)构建工具

两者都有本人的构建工具

  • React ==> Create React APP
  • Vue ==> vue-cli

7)跨平台

  • React ==> React Native
  • Vue ==> Weex

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

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

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

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

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

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

React 如何辨别 Class 组件 和 Function 组件

个别的形式是借助 typeof 和 Function.prototype.toString 来判断以后是不是 class,如下:

function isClass(func) {
  return typeof func === 'function'
    && /^class\s/.test(Function.prototype.toString.call(func));
}

然而这个形式有它的局限性,因为如果用了 babel 等转换工具,将 class 写法全副转为 function 写法,下面的判断就会生效。

React 辨别 Class 组件 和 Function 组件的形式很奇妙,因为所有的类组件都要继承 React.Component,所以只有判断原型链上是否有 React.Component 就能够了:

AComponent.prototype instanceof React.Component

React 的 Fiber 工作原理,解决了什么问题

  • React Fiber 是一种基于浏览器的单线程调度算法。

React Fiber 用相似 requestIdleCallback 的机制来做异步 diff。然而之前数据结构不反对这样的实现异步 diff,于是 React 实现了一个相似链表的数据结构,将原来的 递归 diff 变成了当初的 遍历 diff,这样就能做到异步可更新了

refs 的作用是什么,你在什么样的业务场景下应用 refs

  • 操作 DOM,为什么操作 DOM?
  • 场景

    • 图片渲染好后,操作图片宽高。比方做个放大镜性能

constructor 为什么不先渲染?

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

所以:constructor 钩子函数并不是不可短少的,子组件能够在一些状况略去。比方不本人的 state,从 props 中获取的状况

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

调用 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 元素

简述 react 事件机制

当用户在为 onClick 增加函数时,React 并没有将 Click 工夫绑定在 DOM 下面
而是在 document 处监听所有反对的事件,当事件产生并冒泡至 document 处时,React 将事件内容封装交给中间层 SyntheticEvent(负责所有事件合成)
所以当事件触发的时候,对应用对立的散发函数 dispatchEvent 将指定函数执行。React 在本人的合成事件中重写了 stopPropagation 办法,将 isPropagationStopped 设置为 true,而后在遍历每一级事件的过程中依据此遍历判断是否继续执行。这就是 React 本人实现的冒泡机制

redux 有什么毛病

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

高阶组件的利用场景

权限管制

利用高阶组件的 条件渲染 个性能够对页面进行权限管制,权限管制个别分为两个维度: 页面级别 页面元素级别

// HOC.js    
function withAdminAuth(WrappedComponent) {    
    return class extends React.Component {    
        state = {isAdmin: false,}    
        async componentWillMount() {const currentRole = await getCurrentUserRole();    
            this.setState({isAdmin: currentRole === 'Admin',});    
        }    
        render() {if (this.state.isAdmin) {return <WrappedComponent {...this.props} />;    
            } else {return (<div> 您没有权限查看该页面,请分割管理员!</div>);    
            }    
        }    
    };    
}

// 应用
// pages/page-a.js    
class PageA extends React.Component {constructor(props) {super(props);    
        // something here...    
    }    
    componentWillMount() {// fetching data}    
    render() {// render page with data}    
}    
export default withAdminAuth(PageA);    

可能你曾经发现了,高阶组件其实就是装璜器模式在 React 中的实现:通过给函数传入一个组件(函数或类)后在函数外部对该组件(函数或类)进行性能的加强(不批改传入参数的前提下),最初返回这个组件(函数或类),即容许向一个现有的组件增加新的性能,同时又不去批改该组件,属于 包装模式(Wrapper Pattern) 的一种。

什么是装璜者模式:在不扭转对象本身的前提下在程序运行期间动静的给对象增加一些额定的属性或行为

能够进步代码的复用性和灵活性

再对高阶组件进行一个小小的总结:

  • 高阶组件 不是组件 一个把某个组件转换成另一个组件的 函数
  • 高阶组件的次要作用是 代码复用
  • 高阶组件是 装璜器模式在 React 中的实现

封装组件的准则

封装准则

1、繁多准则:负责繁多的页面渲染

2、多重职责:负责多重职责,获取数据,复用逻辑,页面渲染等

3、明确承受参数:必选,非必选,参数尽量设置以_结尾,防止变量反复

4、可扩大:需要变动可能及时调整,不影响之前代码

5、代码逻辑清晰

6、封装的组件必须具备高性能,低耦合的个性

7、组件具备繁多职责:封装业务组件或者根底组件,如果不能给这个组件起一个有意义的名字,证实这个组件承当的职责可能不够繁多,须要持续抽组件,直到它能够是一个独立的组件即可

React key 是干嘛用的 为什么要加?key 次要是解决哪一类问题的

Keys 是 React 用于追踪哪些列表中元素被批改、被增加或者被移除的辅助标识。在开发过程中,咱们须要保障某个元素的 key 在其同级元素中具备唯一性。

在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是早先创立的还是被挪动而来的元素,从而缩小不必要的元素重渲染此外,React 还须要借助 Key 值来判断元素与本地状态的关联关系。

注意事项:

  • key 值肯定要和具体的元素—一对应;
  • 尽量不要用数组的 index 去作为 key;
  • 不要在 render 的时候用随机数或者其余操作给元素加上不稳固的 key,这样造成的性能开销比不加 key 的状况下更蹩脚。

React 中 keys 的作用是什么?

KeysReact 用于追踪哪些列表中元素被批改、被增加或者被移除的辅助标识

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

我当初有一个 button,要用 react 在下面绑定点击事件,要怎么做?

class Demo {render() {return <button onClick={(e) => {alert('我点击了按钮')
    }}>
      按钮
    </button>
  }
}

你感觉你这样设置点击事件会有什么问题吗?

因为 onClick 应用的是匿名函数,所有每次重渲染的时候,会把该 onClick 当做一个新的 prop 来解决,会将外部缓存的 onClick 事件进行从新赋值,所以绝对间接应用函数来说,可能有一点的性能降落

批改

class Demo {onClick = (e) => {alert('我点击了按钮')
  }

  render() {return <button onClick={this.onClick}>
      按钮
    </button>
  }

类组件 (Class component) 和函数式组件 (Functional component) 之间有何不同

  • 类组件不仅容许你应用更多额定的性能,如组件本身的状态和生命周期钩子,也能使组件间接拜访 store 并维持状态
  • 当组件仅是接管 props,并将组件本身渲染到页面时,该组件就是一个 ‘ 无状态组件 (stateless component)’,能够应用一个纯函数来创立这样的组件。这种组件也被称为哑组件(dumb components) 或展现组件

什么起因会促使你脱离 create-react-app 的依赖

当你想去配置 webpack 或 babel presets。

对虚构 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 等。

这段代码有什么问题?

class App extends Component {constructor(props) {super(props);
    this.state = {
      username: "有课前端网",
      msg: " ",
    };
  }
  render() {return <div> {this.state.msg}</div>;
  }
  componentDidMount() {this.setState((oldState, props) => {
      return {msg: oldState.username + "-" + props.intro,};
    });
  }
}

render (< App intro=” 前端技术业余学习平台 ”></App>,ickt)
在页面中失常输入“有课前端网 - 前端技术业余学习平台”。然而这种写法很少应用,并不是罕用的写法。React 容许对 setState 办法传递一个函数,它接管到先前的状态和属性数据并返回一个须要批改的状态对象,正如咱们在下面所做的那样。它岂但没有问题,而且如果依据以前的状态(state)以及属性来批改以后状态,举荐应用这种写法。

何为 reducer

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

(组件的)状态 (state) 和属性 (props) 之间有何不同

State 是一种数据结构,用于组件挂载时所需数据的默认值。State 可能会随着工夫的推移而产生渐变,但少数时候是作为用户事件行为的后果。

Props(properties 的简写)则是组件的配置。props 由父组件传递给子组件,并且就子组件而言,props 是不可变的(immutable)。组件不能扭转本身的 props,然而能够把其子组件的 props 放在一起(对立治理)。Props 也不仅仅是数据 – 回调函数也能够通过 props 传递。

redux 是如何更新值得

用户发动操作之后,dispatch 发送 action,依据 type,触发对于的 reducer,reducer 就是一个纯函数,接管旧的 state 和 action,返回新的 state。通过 subscribe(listener)监听器,派发更新。

正文完
 0