疯狂的技术宅

以前出于工作目的,编写和翻译了大量的技术文章,以前端为主,删掉了过时的、毫无营养的内容,留下的都是精华。


  • 首页

  • 分类

  • 标签

  • 归档

  • 关于本站

  • 回到主站

  • 搜索

一道 React 面试题:在浏览器、组件和元素中都渲染了些什么?

时间: 2020-09-18 分类: 前端面试   字数: 1474 字 阅读: 3分钟
标签: #面试题# #React# #渲染#
  • 本文译自:https://medium.com/edge-coders/react-interview-question-what-gets-rendered-in-the-browser-a-component-or-an-element-1b3eac777c85
  • 译者:疯狂的技术宅

这道题的答案有点复杂。

首先要搞清楚 element 和 component 是不是一回事?

Image for post

从技术上来说,ReactDOM 不会在 DOM 中渲染 React 组件或 React 元素。它渲染由其组件实例支持的 DOM 元素。对于类组件来说这是正确的。但是对于函数组件,ReactDOM 仅渲染 DOM 元素。函数组件没有实例(可以通过 this 访问),因此在使用函数组件时,ReactDOM 会渲染由函数返回的元素所生成的 DOM 元素。

你需要在这里理解的是,React 元素不同于 DOM 元素。 React 元素只是 HTML 元素、React 组件或它们的混合的“描述”。

好吧,一个更好的面试题可能应该这样问:当你在JSX中使用 <MyComponent/> 之类的东西时,它是组件、元素还是实例?

这是一个元素,但不是 DOM 元素,而是一个 React元 素。因为任何 JSX 标签都会被转换为 React.createElement 再去调用。

但是要想让 React 继续使用这个 React 元素的话,必须调用一个函数或从一个类中创建实例。

你可能会在一些 React 教程中看到 组件(component)、元素(element) 和 实例(instance) 这些词。我在这里混用这些词是不对的,但是我认为 React 的初学者需要了解它们的区别。 React 官方博客上有一篇文章专门说明这些概念 ,但我认为这些内容对于初学者来说还远远不够。

以下是这些术语的简单定义:

  • React Component 是模板,蓝图,全局定义的。可以是函数或类(带有渲染功能)。
  • React Element 是从组件中返回的东西。这个对象实际上描述了组件所代表的 DOM 节点。对于函数组件来说,此元素是函数返回的对象。对于类组件,元素是组件的渲染函数返回的对象。 React 元素不是我们在浏览器中所看到的。它们只是内存中的对象,我们无法对其进行任何更改。
  • React 在其内部通过创建、更新和销毁 instance 来找出需要渲染给浏览器的 DOM 元素树。使用类组件时,通常将其浏览器渲染的 DOM 元素称为组件实例。你可以渲染同一组件的多个实例。实例是你在基于类的组件内部使用的 this 关键字。你不需要手动从类创建实例,只需要记住它就在 React 的内存中即可。
  • 基于函数的 React 元素没有实例。一个函数组件仍然可以被多次渲染,但是 React 不会将本地实例与每个渲染相关联。它只是用函数的调用来确定要为该函数渲染的 DOM 元素。

最重要的是,ReactDOM 不会在浏览器中渲染组件,也不会渲染元素(这里的术语元素代表 React.createElement 的返回值)。它也不渲染实例。 它只渲染 DOM 元素。

不幸的是,使用术语组件既指模板又指通过模板使用的任何一种实例或者调用,这似乎是很普遍的。人们对此感到困惑很正常,这挺痛苦的。

这究竟是怎么回事?

每个 React 应用都从一个使用 React element 的 render 调用开始。下面以 reactjs.org 官网提供的 HelloMessage 案例作为例子,我对这个例子稍微做了一些修改,使其具有了函数组件:

const Today = () => (
  <div>Today is {new Date().toDateString()}</div>
);class HelloMessage extends React.Component {
  render() {
    return (
      <React.Fragment>
        <div>Hello {this.props.name}</div>
        <Today />
      </React.Fragment>
    );
  }
}ReactDOM.render(
  <HelloMessage name="Taylor" />,
  mountNode
);

第一个 React 元素是我们在 ReactDOM.render 调用中开始的元素:

<HelloMessage name="Taylor" /> // 这是 React element

这个 React 元素描述了要渲染的 DOM 树应该以 HelloMessage 组件和值等于 Taylor 的 prop name 开始。

现在回答问题:HelloMessage 是什么?

每当 React 元素描述一个 React 组件时(就像上面的 React 元素一样),React 使用该组件将描述替换为组件返回的内容。这时它将会为基于类的组件创建一个实例,并将该实例的引用保留在内存中。它不会为基于函数的组件创建任何内容。它只是调用它们。

从 HelloMessage 组件返回的是一个描述 React.Fragment 组件的 React 元素。

回答问题: React.Fragment 是什么?

React 会持续不断的减少这些组件的未知描述,直到只存在有效的 DOM 节点。 React.Fragment 的描述被翻译成 2 个React 元素,一个描述 div ,另一个描述 Today 组件。

回答问题:代码中的 Today 什么是?

它调用 Today 函数来找出最后一个问题。 Today 函数返回描述一个 div 的 React 元素。

至此,virtual 树中包含了所有描述 DOM 节点的 React 元素。 React 通过一致性比较算法找出要在浏览器中更新的内容。用组件实例所转换的树节点保留修改该实例的能力。

标签: #面试题# #React# #渲染#

标题:一道 React 面试题:在浏览器、组件和元素中都渲染了些什么?

链接:https://fe-tech.viewnode.com/post/202009/18/

作者:疯狂的技术宅

声明: 本博客文章除特别声明外,均采用 CC BY-NC-ND 4.0 国际许可协议( 知识共享署名-非商业性使用-禁止演绎 4.0),转载请注明出处!

浅析常见的算法范式
怎样设计一个 JavaScript 插件系统
  • 文章目录
  • 站点概览
疯狂的技术宅

疯狂的技术宅

退休程序员,硬件发烧友,人工智能爱好者。写写代码喝喝茶,晒晒太阳带带娃。

457 日志
8 分类
583 标签
GitHub
友情链接
  • viewnode
  • mofish
标签云
  • Javascript 172
  • Node.Js 62
  • Vue 36
  • Typescript 28
  • 实战项目 28
  • 面试 21
  • React 20
  • Css 17
  • 面试题 16
  • 教程 13
  • Promise 12
  • Chrome 9
  • Debug 9
  • 调试 9
  • 资源 9
  • Deno 8
  • Dom 8
  • 杂谈 8
  • 正则表达式 8
  • 测试 8
  • 这究竟是怎么回事?
© 2018 - 2022 疯狂的技术宅 All Rights Reserved
Powered by - Hugo v0.99.0 / Theme by - NexT
Storage by 俺的服务器 / 冀ICP备2022010157号
0%