作者:Samer Buna翻译:疯狂的技术宅
原文:https://medium.com/edge-coder...
未经允许严禁转载
这道题的答案有点复杂。
首先要搞清楚 element 和 component 是不是一回事?
从技术上来说,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 元素。
不幸的是,使用术语组件既指模板又指通过模板使用的任何一种实例或者调用,这似乎是很普遍的。人们对此感到困惑很正常,这挺痛苦的。
What’s the story here?
这是什么故事?
每个 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 通过一致性比较算法找出要在浏览器中更新的内容。用组件实例所转换的树节点保留修改该实例的能力。
本文首发微信公众号:前端先锋
欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章
欢迎继续阅读本专栏其它高赞文章:
- 深入理解Shadow DOM v1
- 一步步教你用 WebVR 实现虚拟现实游戏
- 13个帮你提高开发效率的现代CSS框架
- 快速上手BootstrapVue
- JavaScript引擎是如何工作的?从调用栈到Promise你需要知道的一切
- WebSocket实战:在 Node 和 React 之间进行实时通信
- 关于 Git 的 20 个面试题
- 深入解析 Node.js 的 console.log
- Node.js 究竟是什么?
- 30分钟用Node.js构建一个API服务器
- Javascript的对象拷贝
- 程序员30岁前月薪达不到30K,该何去何从
- 14个最好的 JavaScript 数据可视化库
- 8 个给前端的顶级 VS Code 扩展插件
- Node.js 多线程完全指南
- 把HTML转成PDF的4个方案及实现
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。