• 前端一面经典react面试题(边面边更)


    react 的虚拟dom是怎么实现的

    首先说说为什么要使用Virturl DOM,因为操作真实DOM的耗费的性能代价太高,所以react内部使用js实现了一套dom结构,在每次操作在和真实dom之前,使用实现好的diff算法,对虚拟dom进行比较,递归找出有变化的dom节点,然后对其进行更新操作。为了实现虚拟DOM,我们需要把每一种节点类型抽象成对象,每一种节点类型有自己的属性,也就是prop,每次进行diff的时候,react会先比较该节点类型,假如节点类型不一样,那么react会直接删除该节点,然后直接创建新的节点插入到其中,假如节点类型一样,那么会比较prop是否有更新,假如有prop不一样,那么react会判定该节点有更新,那么重渲染该节点,然后在对其子节点进行比较,一层一层往下,直到没有子节点

    如何配置 React-Router 实现路由切换

    (1)使用 组件

    路由匹配是通过比较 的 path 属性和当前地址的 pathname 来实现的。当一个 匹配成功时,它将渲染其内容,当它不匹配时就会渲染 null。没有路径的 将始终被匹配。

    // when location = { pathname: '/about' }
    <Route path='/about' component={
       About}/> // renders 
    <Route path='/contact' component={
       Contact}/> // renders null
    <Route component={
       Always}/> // renders 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (2)结合使用 组件和 组件

    用于将 分组。

    <Switch>
        <Route exact path="/" component={
       Home} />
        <Route path="/about" component={
       About} />
        <Route path="/contact" component={
       Contact} />
    </Switch>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    不是分组 所必须的,但他通常很有用。 一个 会遍历其所有的子 元素,并仅渲染与当前地址匹配的第一个元素。

    (3)使用 组件

    组件来在你的应用程序中创建链接。无论你在何处渲染一个 ,都会在应用程序的 HTML 中渲染锚()。

    <Link to="/">Home</Link>   
    // Home
    
    
    • 1
    • 2
    • 3

    是一种特殊类型的 当它的 to属性与当前地址匹配时,可以将其定义为"活跃的"。

    // location = { pathname: '/react' }
    <NavLink to="/react" activeClassName="hurray">
        React
    </NavLink>
    // React
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    当我们想强制导航时,可以渲染一个,当一个渲染时,它将使用它的to属性进行定向。

    useEffect和useLayoutEffect的区别

    useEffect
    基本上90%的情况下,都应该用这个,这个是在render结束后,你的callback函数执行,但是不会block browser painting,算是某种异步的方式吧,但是class的componentDidMount 和componentDidUpdate是同步的,在render结束后就运行,useEffect在大部分场景下都比class的方式性能更好.
    useLayoutEffect
    这个是用在处理DOM的时候,当你的useEffect里面的操作需要处理DOM,并且会改变页面的样式,就需要用这个,否则可能会出现出现闪屏问题, useLayoutEffect里面的callback函数会在**DOM更新完成后立即执行,但是会在浏览器进行任何绘制之前运行完成,**阻塞了浏览器的绘制.

    对虚拟 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中发起网络请求应该在哪个生命周期中进行?为什么?

    对于异步请求,最好放在componentDidMount中去操作,对于同步的状态改变,可以放在componentWillMount中,一般用的比较少。

    如果认为在componentWillMount里发起请求能提早获得结果,这种想法其实是错误的,通常componentWillMount比componentDidMount早不了多少微秒,网络上任何一点延迟,这一点差异都可忽略不计。

    react的生命周期: constructor() -> componentWillMount() -> render() -> componentDidMount()

    上面这些方法的调用是有次序的,由上而下依次调用。

    • constructor被调用是在组件准备要挂载的最开始,此时组件尚未挂载到网页上。
    • componentWillMount方法的调用在constructor之后,在render之前,在这方法里的代码调用setState方法不会触发重新render,所以它一般不会用来作加载数据之用。
    • componentDidMount方法中的代码,是在组件已经完全挂载到网页上才会调用被执行,所以可以保证数据的加载。此外,在这方法中调用setState方法,会触发重新渲染。所以,官方设计这个方法就是用来加载外部数据用的,或处理其他的副作用代码。与组件上的数据无关的加载,也可以在constructor里做,但constructor是做组件state初绐化工作,并不是做加载数据这工作的,constructor里也不能setState,还有加载的时间太长或者出错,页面就无法加载出来。所以有副作用的代码都会集中在componentDidMount方法里。

    总结:

    • 跟服务器端渲染(同构)有关系,如果在componentWillMount里面获取数据,fetch data会执行两次,一次在服务器端一次在客户端。在componentDidMount中可以解决这个问题,componentWillMount同样也会render两次。
    • 在componentWillMount中fetch data,数据一定在render后才能到达,如果忘记了设置初始状态,用户体验不好。
    • react16.0以后,componentWillMount可能会被执行多次。

    对 React-Intl 的理解,它的工作原理?

    React-intl是雅虎的语言国际化开源项目FormatJS的一部分,通过其提供的组件和API可以与ReactJS绑定。

    React-intl提供了两种使用方法,一种是引用React组件,另一种是直接调取API,官方更加推荐在React项目中使用前者,只有在无法使用React组件的地方,才应该调用框架提供的API。它提供了一系列的React组件,包括数字格式化、字符串格式化、日期格式化等。

    在React-intl中,可以配置不同的语言包,他的工作原理就是根据需要,在语言包之间进行切换。

    参考:前端react面试题详细解答

    HOC相比 mixins 有什么优点?

    HOC 和 Vue 中的 mixins 作用是一致的,并且在早期 React 也是使用 mixins 的方式。但是在使用 class 的方式创建组件以后,mixins 的方式就不能使用了,并且其实 mixins 也是存在一些问题的,比如:

    • 隐含了一些依赖,比如我在组件中写了某个 state 并且在 mixin 中使用了,就这存在了一个依赖关系。万一下次别人要移除它,就得去 mixin 中查找依赖
    • 多个 mixin 中可能存在相同命名的函数,同时代码组件中也不能出现相同命名的函数,否则就是重写了,其实我一直觉得命名真的是一件麻烦事。。
    • 雪球效应,虽然我一个组件还是使用着同一个 mixin,但是一个 mixin 会被多个组件使用,可能会存在需求使得 mixin 修改原本的函数或者新增更多的函数,这样可能就会产生一个维护成本

    HOC 解决了这些问题,并且它们达成的效果也是一致的,同时也更加的政治正确(毕竟更加函数式了)。

    讲讲什么是 JSX ?

    Facebook 第一次发布 React 时,他们还引入了一种新的 JS 方言 JSX,将原始 HTML 模板嵌入到 JS 代码中。JSX 代码本身不能被浏览器读取,必须使用Babelwebpack等工具将其转换为传统的JS。很多开发人员就能无意识使用 JSX,因为它已经与 React 结合在一直了。

    class MyComponent extends React.Component {
       
      render() {
       
        let props = this.props;
        return (
          <div className="my-component">
            <a href={
       props.url}>{
       props.name}</a>
          </div>
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    • 类组件不仅允许你使用更多额外的功能,如组件自身的状态和生命周期钩子,也能使组件直接访问 store 并维持状态
    • 当组件仅是接收 props,并将组件自身渲染到页面时,该组件就是一个
  • 相关阅读:
    时间戳 太平洋夏令时间和本地时间相互转换及自定义夏令时
    RocketMQ(17)——Broker可配置参数
    GA-RPN:引导锚点的建议区域网络
    窗口函数的5种方法总结
    crypto加密
    【Proteus仿真】8位数码管动态扫描显示变化数据
    获取微信公众号发布内容封面图片url
    Uniapp自定义启动图在线生成storyboard(适用于Uniapp)
    使用 shell 脚本拼接 srt 字幕文件 (srtcat)
    鲈鱼的面试题库+答案
  • 原文地址:https://blog.csdn.net/beifeng11996/article/details/127915499