zoukankan      html  css  js  c++  java
  • react.js 从零开始(七)React (虚拟)DOM

    React 元素

    React 中最主要的类型就是 ReactElement。它有四个属性:typepropskey 和ref。它没有方法,并且原型上什么都没有。

    可以通过 React.createElement 创建该类型的一个实例。

    var root = React.createElement('div');
    

    为了渲染一个新的树形结构到 DOM 中,你创建若干个 ReactElement,然后传给React.render 作为第一个参数,同时将第二个参数设为一个正规的 DOM 元素HTMLElement 或者 SVGElement)。不要混淆 ReactElement 实例和 DOM 元素 实例。一个 ReactElement 实例是一个轻量的,无状态的,不可变的,虚拟的 DOM 元素 的表示。是一个虚拟 DOM。

    React.render(root, document.body);
    

    要添加属性到 DOM 元素,把属性对象作为第二个参数传入 React.render,把子级作为第三个参数传给 React.render

    var child = React.createElement('li', null, 'Text Content');
    var root = React.createElement('ul', { className: 'my-list' }, child);
    React.render(root, document.body);
    

    如果使用 React JSX 语法,这些 ReactElement 实例自动创建。所以,如下代码是等价的:

    var root = <ul className="my-list">
                 <li>Text Content</li>
               </ul>;
    React.render(root, document.body);
    

    工厂

    一个 ReactElement 工厂就是一个简单的函数,该函数生成一个带有特殊 type 属性的ReactElement。React 有一个内置的辅助方法用于创建工厂函数。事实上该方法就是这样的:

    function createFactory(type){
      return React.createElement.bind(null, type);
    }
    

    该函数能创建一个方便的短函数,而不是总调用 React.createElement('div')

    var div = React.createFactory('div');
    var root = div({ className: 'my-div' });
    React.render(root, document.body);
    

    React 已经内置了常用 HTML 标签的工厂函数:

    var root = React.DOM.ul({ className: 'my-list' },
                 React.DOM.li(null, 'Text Content')
               );
    

    如果使用 JSX 语法,就不需要工厂函数了。JSX 已经提供了一种方便的短函数来创建ReactElement 实例。

    React 节点

    一个 ReactNode 可以是:

    • ReactElement
    • string (又名 ReactText
    • number (又名 ReactText
    • ReactNode 实例数组 (又名 ReactFragment

    这些被用作其它 ReactElement 实例的属性,用于表示子级。实际上它们创建了一个ReactElement 实例树。 (These are used as properties of other ReactElements to represent children. Effectively they create a tree of ReactElements.)

    React 组件

    在使用 React 开发中,可以仅使用 ReactElement 实例,但是,要充分利用 React,就要使用 ReactComponent 来封装状态化的组件。

    一个 ReactComponent 类就是一个简单的 JavaScript 类(或者说是“构造函数”)。

    var MyComponent = React.createClass({
      render: function() {
        ...
      }
    });
    

    当该构造函数调用的时候,应该会返回一个对象,该对象至少带有一个 render 方法。该对象指向一个 ReactComponent 实例。

    var component = new MyComponent(props); // never do this
    

    除非为了测试,正常情况下不要自己调用该构造函数。React 帮你调用这个函数。

    相反,把 ReactComponent 类传给 createElement,就会得到一个 ReactElement 实例。

    var element = React.createElement(MyComponent);
    

    或者使用 JSX:

    var element = <MyComponent />;
    

    当该实例传给 React.render 的时候,React 将会调用构造函数,然后创建并返回一个ReactComponent

    var component = React.render(element, document.body);
    

    如果一直用相同的 ReactElement 类型和相同的 DOM 元素容器调用 React.render,将会总是返回相同的实例。该实例是状态化的。

    var componentA = React.render(<MyComponent />, document.body);
    var componentB = React.render(<MyComponent />, document.body);
    componentA === componentB; // true
    

    这就是为什么不应该创建你自己的实例。相反,在创建之前,ReactElement 是一个虚拟的ReactComponent。新旧 ReactElement 可以比对,从而决定是创建一个新的ReactComponent 实例还是重用已有的实例。

    ReactComponent 的 render 方法应该返回另一个 ReactElement,这就允许组件被组装。 (The render method of a ReactComponent is expected to return another ReactElement. This allows these components to be composed. Ultimately the render resolves intoReactElement with a string tag which instantiates a DOM Element instance and inserts it into the document.)

    正式的类型定义

    入口点(Entry Point)

    React.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;
    

    节点和元素(Nodes and Elements)

    type ReactNode = ReactElement | ReactFragment | ReactText;
    
    type ReactElement = ReactComponentElement | ReactDOMElement;
    
    type ReactDOMElement = {
      type : string,
      props : {
        children : ReactNodeList,
        className : string,
        etc.
      },
      key : string | boolean | number | null,
      ref : string | null
    };
    
    type ReactComponentElement<TProps> = {
      type : ReactClass<TProps>,
      props : TProps,
      key : string | boolean | number | null,
      ref : string | null
    };
    
    type ReactFragment = Array<ReactNode | ReactEmpty>;
    
    type ReactNodeList = ReactNode | ReactEmpty;
    
    type ReactText = string | number;
    
    type ReactEmpty = null | undefined | boolean;
    

    类和组件(Classes and Components)

    type ReactClass<TProps> = (TProps) => ReactComponent<TProps>;
    
    type ReactComponent<TProps> = {
      props : TProps,
      render : () => ReactElement
    };
  • 相关阅读:
    Linux IO接口 监控 (iostat)
    linux 防火墙 命令
    _CommandPtr 添加参数 0xC0000005: Access violation writing location 0xcccccccc 错误
    Visual Studio自动关闭
    Linux vsftpd 安装 配置
    linux 挂载外部存储设备 (mount)
    myeclipse 9.0 激活 for win7 redhat mac 亲测
    英文操作系统 Myeclipse Console 乱码问题
    Linux 基本操作命令
    linux 查看系统相关 命令
  • 原文地址:https://www.cnblogs.com/tomblog/p/4822436.html
Copyright © 2011-2022 走看看