react.js 从零开始(七)React (虚拟)DOM
React 元素
React 中最主要的类型就是 ReactElement。它有四个属性:type,props,key 和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 可以是:
ReactElementstring(又名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
};
react.js 从零开始(七)React (虚拟)DOM的更多相关文章
- react快速上手一(使用js语法,创建虚拟DOM元素)
1.装包,引包 首先需要安装两个包 react ,react-dom cnpm i react react-dom 介绍下这两个包: react:专门用来创建React组件,组件生命周期等这些东西. ...
- react.js 从零开始(一)
React 是什么? 网络上的解释很多...我这里把他定义为 通过javascript 的形式组件化 html的框架... React 仅仅是 VIEW 层. React 提供了模板语法以及一些函数钩 ...
- react起步——从零开始编写react项目
# index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> ...
- react.js 从零开始(五)React 中事件的用法
事件系统 虚拟事件对象 事件处理器将会传入虚拟事件对象的实例,一个对浏览器本地事件的跨浏览器封装.它有和浏览器本地事件相同的属性和方法,包括 stopPropagation() 和 prevent ...
- react.js 从零开始(四)React 属性和状态详解
属性的含义和用法: 1.属性的含义. props=properties 属性:一个事物的性质和关系. 属性往往与生俱来,不可以修改. 2. 属性的用法. <Helloworld name=??? ...
- react.js 从零开始(三)JSX 语法及特点介绍
什么是jsx? jsx = JavaScript + xml jsx 是一种 Ecmascript 的一种新标准. jsx 是一种 带有结构性的语法. jsx 的特点: 1.类xml语法易于理解. 2 ...
- react.js 从零开始(六)Reconciliation
Reconciliation React 的关键设计目标是使 API 看起来就像每一次有数据更新的时候,整个应用重新渲染了一样.这就极大地简化了应用的编写,但是同时使 React 易于驾驭,也是一 ...
- react.js 从零开始(二)组件的生命周期
什么是生命周期? 组件本质上是一个状态机,输入确定,输出一定确定. 当状态改变的时候 会触发不同的钩子函数,可以让开发者做出响应.. 一个组件的生命周期可以概括为 初始化:状态下 可以自定义的函数 g ...
- React diff机制(介绍虚拟DOM的机制)
https://segmentfault.com/a/1190000004003055
随机推荐
- WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(二)实现IRequestChannel(2016-03-15 12:35)
这是这个系列的第二篇,其他的文章请点击下列目录 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息编码(一)概要设计 WCF扩展之实现ZeroMQ绑定和protocolBuffer消息 ...
- 在JAVA中使用LUA脚本记,javaj调用lua脚本的函数(转)
最近在做一些奇怪的东西,需要Java应用能够接受用户提交的脚本并执行,网络部分我选择了NanoHTTPD提供基本的HTTP服务器支持,并在Java能承载的许多脚本语言中选择了很久,比如Rhino,Jy ...
- Java RMI(远程方法调用) 实例与分析
目的: 通过本文,可以加深对Java RMI的理解,知道它的工作原理,怎么使用等. 也为了加深我自己的理解,故整理成文.不足之处,还望指出. 概念解释: RMI(RemoteMethodInvocat ...
- 2014年CCNU-ACM暑期集训总结
2014年CCNU-ACM暑期集训总结 那个本期待已久的暑期集训居然就这种.溜走了.让自己有点措手不及.很多其它的是对自己的疑问.自己是否能在ACM这个领域有所成就.带着这个疑问,先对这个暑假做个总结 ...
- 学习pthreads,创建和终止多线程
更CPU多线程编程,通过笔者的研究发现,,pthreads使用日趋广泛.它是螺纹POSIX标准,它定义了一组线程的创建和操作API. 配置环境见上博客文章.配置环境后,只需要加入#include &l ...
- Android Studio如何引用jar包裹(不gradle)
这和eclipse最大的区别.与非常人的预期开始Android Studio我们很不高兴这一套. 它直接在地图上.首先通过File->Projcet structure打开project结构界面 ...
- [原创].NET 分布式架构开发实战之一 故事起源
原文:[原创].NET 分布式架构开发实战之一 故事起源 .NET 分布式架构开发实战之一 故事起源 前言:本系列文章主要讲述一个实实在在的项目开发的过程,主要包含:提出问题,解决问题,架构设计和各个 ...
- Jedis连接
Jedis连接 到场api中的jedis.我们能够发现,jedis类提供了4个构造方法.都可用于连接: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc29 ...
- HDU 1677 Nested Dolls
过了之后感觉曾经真的做过这样的类型的题. 之前一直非常疑惑二级排序的优先级问题,如今发现二级排序真的没有绝对的优先级. 对于此题,若按W排序,则有1到i件物品的W均小于等于第i+1件物品(设为A)的W ...
- MD5和Base64
一. 简述 MD5: 全称为message digest algorithm 5(信息摘要算法), 能够进行加密, 可是不能解密, 属于单向加密, 通经常使用于文件校验 Base64: 把随意序列的8 ...