资讯专栏INFORMATION COLUMN

[译]React 元素 vs React 组件 vs 组件支撑实例

gnehc / 1271人阅读

摘要:元素和组件实例都不表示真实元素。我希望这篇文章能够帮助你理清这些术语参考资料翻译成支撑实例来自于理解中方法创建组件的声明式编程和命令式编程的比较对循环提示增加的研究精髓之一算法

本篇为译文,原文出处:React Elements vs React Components vs Component Backing Instances

许多人可能听说过 Facebook 的 React 库,并在自己的工作或项目中使用它。React 是非常流行的,使开发用户界面变得简单且符合声明式编程(译者注:声明式编程可以参考声明式编程和命令式编程的比较)。

正如题目所示,React 有几个概念遍及其文档,这(几个概念)可能会让新React用户困惑。例如,你在 Glossary、Top-Level API 和 Explanation on Refs 这几章中检索 “React Element”、“React Component” 和 “Component Backing Instance”,你会发现这几个术语遍及各处,已经是 React 的绝对的核心。

这篇文章不是一篇 React 的教程,更多的是分享我最近学习 React 而得到的一些(知识)。因此,这篇文章是针对之前已经涉猎过 React 的人们,我会假设你已经熟悉 React 一些核心概念和语法。

React元素是什么?

React 元素这个概念对于 React 来说很重要,但是我坚信一点,因为使用 React 和 JSX 来构建用户界面过于简单,从而导致可能在最初错过这个概念。如果你之前用过 React + JSX,毫无疑问的说,在你的 JS 文件中书写类 HTML 语法更加符合你的习惯(译者注:Habit is second nature. 习惯成自然)。在这种(书写类HTML语法)假象之下,JSX 语法实际上被编译成特殊的函数调用 — React.createElement()。 猜猜 React.createElement()会产生什么?耶,你猜对了,就是 React 元素。让我们看一个转换过程的例子:

// 使用 JSX 语法
var helloWorld = 
Hello World!
; // 然后是 JSX 被编译成 JavaScript 后的结果 var helloWorld = React.createElement( "div", null, "Hello World!" ); // 再是处理成 JavaScript 简单对象后看起来类似这样 var helloWorld = { key: null, props: { children: "Hello World!" // more stuff in here }, ref: null, type: "div" // more stuff in here };

React 元素是由一些属性(properties)构成的 JavaScript 简单对象(plain old JavaScript objects,译者注:关于更多解释可以看 Plain Old JavaScript,What is a plainObject in JavaScript?):

key - 属性 key 是用来在一组相同类型的 React 元素构成的 Array 中标识唯一特定 React 元素。你不必提供一个值给它(译者注:在新版 React 中,如果在循环一组相同类型的 React 元素时不指定 key,会报一个 warning 错误,具体可以参考 React 对循环 warning 提示增加 key 的研究),但是如果你给 key 提供一个值,React 将能够进行优化,使重新渲染过程更高效。

props - 属性props 恰恰是你所认为的: 它是向下传递给子组件(child components)的所有 props 和 values 的映射(集合)。

ref - 属性ref 用来访问与这个 React 元素相关联的经过(浏览器或渲染引擎)渲染处理后的底层 DOM 元素。

type - 属性type 将是两种格式之一,表示任何有效的 HTML 元素的(名称)字符串 或 指向 React 组件类的引用。

此时, 了解每个属性所有细节并不重要。最大的收获在于,React 元素仅仅是 JavaScript 简单对象(plain old JavaScript objects),用来描述组件的 HTML 应是怎样的结构,这个对象上不包含任何方法(Methods),仅仅只有数据。

通过之前 helloWorld React 元素的例子告诉你,helloWorld表示一个子节点为“Hello World!”文本的 div 标签。即使你创建了一个更复杂的 JSX 例子,生成的 React 元素仍将是一个 JavaScript 对象,配合其他嵌套 React 元素描述 HTML 将是怎样的结构。如果这让你感觉熟悉,是因为这正是虚拟 DOM(Virtual DOM)是什么(的解释) - 它是 DOM 在特定时间段应该是怎样的结构的描述,通过 React 元素声明来表示。

React组件是什么?

不同于 React 元素,你可能对 React 组件更熟悉一些。如果你曾写过类似下面例子的代码,那么你之前已经创建过 React 组件类了:

// 这是一个 React 组件类
class CustomForm extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            inputText: "Willson"
        };

        this.handleInputChange = this.handleInputChange.bind(this);
    }

    handleInputChange(e) {
        const inputText = e.target.value;
        this.setState({ inputText });
    }

    render() {
        return (
            

Hello, {this.state.inputText}

); } } /* * 我假设你有可用的 React 和 ReactDom,以及 * 一个 id 为 "root" 的 HTML 元素 * ReactDOM.render() 的返回值是组件实例 */ var componentInstance = ReactDOM.render(, document.getElementById("root"));

上面的例子是用 ES2015 新的 Class 语法写的,但它几乎相当于使用 React.createClass()。你也许熟悉编写这些组件类,但重要的是(React文档中所述的)React 组件指代的是一个 React 组件类的实例。

假如你熟悉 JavaScript 的话,当你听到到“实例化一个类”且智商在线时,你可能会考虑使用new操作符。然而,(在 React 中)从不需要你用 new 操作符创建 React 组件。相反的是,你将使用 ReactDOM.render() 把一个 React 元素渲染成一个特定的 DOM 元素,与此同时,ReactDOM.render() 将返回一个 React 组件实例。

ReactDOM.render() 返回的组件实例可以调用在 React 组件类中定义的方法。反过来想一下会让你明白,ReactDOM.render() 是 React 为你实例化一个组件的机制。通常, 你不需要访问组件实例本身, 但我发现在测试 React 组件时, 将组件实例的引用保存下来(对测试)很有帮助。

ReactDOM.render() 有关的最后一个有趣的点是,React 在 ReactDOM.render() 时对虚拟 DOM 执行高效的 diff 算法(译者注: diff 算法延伸阅读)。如果你记得(上面说的),React 元素表示虚拟 DOM(元素),这意味着 ReactDOM.render() 接收一个虚拟 DOM(元素),将其渲染成一个真实 DOM 元素,返回(React 元素 type 指定的)组件实例。在底层,如果你将相同的React元素类型(带有可能不同的 props 值)通过 ReactDOM.render() 渲染成相同的 DOM 元素,React 将执行 diff 算法,对 DOM 元素进行仅必须的最小更改。也许令人惊讶的是,它每次返回相同的组件实例 - 除了更新的 prop 和 state 值。

组件支撑实例是什么?

前两节探讨了 React 元素和 React 组件实例,这两个概念都是 DOM 之上的抽象层。 现在我们将讨论术语“组件支撑实例”,以及它们自身如何与真实 DOM 元素相关联。

// 组件类
class CustomForm extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            inputText: "Willson"
        };

        this.handleInputChange = this.handleInputChange.bind(this);
    }

    handleInputChange(e) {
        const inputText = e.target.value;
        this.setState({ inputText });
    }

    render() {
        return (
            

Hello, {this.state.inputText}

); } } // 组件实例 var componentInstance = ReactDOM.render(, document.getElementById("root")); // DOM 实例 var domInstance = ReactDOM.findDOMNode(componentInstance); // 原文作者这里出了个 Bug,多了一个 D

在前面的实例中,ReactDOM.render() 通过将 React 元素渲染到现有的 DOM 元素中来生成一个组件实例。正如我们已经知道的,组件实例不是真实 DOM 节点。然而,访问与组件实例关联的底层 DOM 节点实际上很简单 - 我们使用 ReactDOM.findDOMNode(),并将组件实例作为其参数传递。那么这与“组件支撑实例”术语有什么关系呢?让我们一脸懵逼的是,React 在其文档的各处将引用的真实 DOM 节点称之为组件支撑实例

总结

这3个术语“React 元素”,“React 组件”和“组件支撑实例”是密切相关的。 由于 JSX 语法被转译为 React.createElement()调用(译者注:理解转译这个概念可以参考 Compiling Vs Transpiling),最终返回我们称之为“React 元素”的 JavaScript 简单对象(plain old JavaScript objects),你可以将 React元素视为基础构建单元。React 组件实例表示下一个抽象层 - ReactDOM.render() 接收一个 React 元素、引用一个真实 DOM 节点、返回一个 React 组件实例。该实例可以访问组件类中定义的方法,但是在单元测试之外很少用到这一点。React 元素和 React 组件实例都不表示真实 DOM 元素。渲染组件实例产生的 DOM 元素被称为组件支撑实例,访问它的主要方式是使用ReactDOM.findDOMNode()

我希望这篇文章能够帮助你理清这些术语!

[参考资料]

Backing Instances 翻译成 支撑实例 来自于 理解React中es6方法创建组件的this

声明式编程和命令式编程的比较

React 对循环 warning 提示增加 key 的研究

react精髓之一---diff算法

Compiling Vs Transpiling

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82673.html

相关文章

  • 2017-08-07 前端日报

    摘要:前端日报精选创建对象从到按钮元素新属性等简介聊聊的设计思想译渐进增强的布局从浮动到到一个少女心满满的例子带你入门中文原创函数式组件的实践框架尝鲜知乎专栏译知乎专栏周刊技术周刊期知乎专栏布局新旧混合写法详解兼容微信组件简介众成翻 2017-08-07 前端日报 精选 JavaScript创建对象—从es5到es6HTML5按钮元素新属性formaction,formenctype等简介聊...

    wudengzan 评论0 收藏0
  • 】函数式的React

    摘要:高阶组件和高阶函数高阶组件是编程中的常见模式。您可以将上面例子中的高阶函数用函数的方式来重新整理如你所见,这就像是一个高阶函数,这个函数接受一个函数,返回一个新的元素。函数式编程范例旨在避免在应用程序中使用状态。 原文:The functional side of React作者:Andrea Chiarelli译者:博轩 React 是现在最流行的 JavaScript 库之一。使用...

    gnehc 评论0 收藏0
  • [] 使用 VS Code 加速前端开发

    摘要:在对比我最近几个月所用的开发工具后,我发现了一些惊人的东西。永远不停止使用。将警告未使用的代码。预检查使用,,和非常有用。不再需要使用开启服务器,创建应用程序,并打开浏览器。尝试使用别的东西,立即出现错误。 原文:Supercharging Frontend Development with VS Code 作者:zachcodes 过去几天,为了在开发 GraphQL / Rea...

    keithxiaoy 评论0 收藏0
  • React专题:react,redux以及react-redux常见一些面试题

    摘要:我们可以为元素添加属性然后在回调函数中接受该元素在树中的句柄,该值会作为回调函数的第一个参数返回。使用最常见的用法就是传入一个对象。单向数据流,比较有序,有便于管理,它随着视图库的开发而被概念化。 面试中问框架,经常会问到一些原理性的东西,明明一直在用,也知道怎么用, 但面试时却答不上来,也是挺尴尬的,就干脆把react相关的问题查了下资料,再按自己的理解整理了下这些答案。 reac...

    darcrand 评论0 收藏0
  • 2017-06-28 前端日报

    摘要:前端日报精选我是如何实现的在线升级热更新功能的张鑫旭鑫空间鑫生活翻译表单的运用第期晋升评审的套路异步编程的四种方式黄博客精选组件设计和分解思考掘金中文译使登录页面变得正确掘金前端从强制开启压缩探究插件运行机制掘金个常用的简 2017-06-28 前端日报 精选 我是如何实现electron的在线升级热更新功能的? « 张鑫旭-鑫空间-鑫生活【翻译】React 表单: Refs 的运用【...

    QLQ 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<