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

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

许多人可以听说过 Facebook 的 React 库,并在本身的事情或项目中运用它。React 是异常盛行的,使开辟用户界面变得简朴且相符声明式编程(译者注:声明式编程可以参考声明式编程和敕令式编程的比较)。

正如问题所示,React 有几个观点普及其文档,这(几个观点)可以会让新React用户疑心。比方,你在 GlossaryTop-Level APIExplanation 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 = <div>Hello World!</div>;

// 然后是 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 JavaScriptWhat 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 (
            <div className="custom-form">
                <div className="custom-form-header">
                    <p>Hello, {this.state.inputText}</p>
                </div>
                <div className="custom-form-body">
                    <input type="text"
                           value={this.state.inputText}
                           onChange={this.handleInputChange} />
                </div>
            </div>
        );
    }
}

/*
 * 我假定你有可用的 React 和 ReactDom,以及  
 * 一个 id 为 "root" 的 HTML 元素
 * ReactDOM.render() 的返回值是组件实例
 */
var componentInstance = ReactDOM.render(<CustomForm />, 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 (
            <div className="custom-form">
                <div className="custom-form-header">
                    <p>Hello, {this.state.inputText}</p>
                </div>
                <div className="custom-form-body">
                    <input type="text"
                           value={this.state.inputText}
                           onChange={this.handleInputChange} />
                </div>
            </div>
        );
    }
}

// 组件实例
var componentInstance = ReactDOM.render(<CustomForm />, 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()

我愿望这篇文章可以协助你理清这些术语!

[参考资料]

    原文作者:lazyboy
    原文地址: https://segmentfault.com/a/1190000009169542
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞