Pure React
React 和 ReactDOM 从0.14版本
之后分为两个文件,这样是为了让 React 和浏览器,DOM之间不存在必然的联系,让React写组件更加的灵活,比如与 React Native结合。
下面从基本概念谈起,然后再介绍React的基本方法。
一.基本概念
1.Virtual DOM
虚拟DOM是指js对象告诉React如何在浏览器中构建UI, 虚拟DOM提供一种描述,React将与浏览器DOM进行交互。
2.React Element
浏览器DOM由DOM元素组成,同样的React DOM 由 React Elements组成.React Element是对实际DOM的一种描述,指导浏览器如何构建DOM。
二.React.createElement()
创建React Elements的方法为React.createElement(),可以看出这个方法和浏览器DOM创建元素的方法一致,签名如下
React.createElement(ElementType, ElementProps, children)
// 返回类型为 一个React Element
比如:
var h1 = React.createElement(
"h1",
{"id": "heading", "data-type": "title"},
"Hello World"
);
// 表示
Hello World
data-reactroot
: 这个特性将自动出现在React Component的根元素上。
什么是React Element呢
React Elements 的实质是 Javascript literal 告诉浏览器如何构建DOM
这个字面量有很多字段比如: key
, ref
, _owner
, _store
, $$typeof
, props
等
{
"$$typeof": Symbol(React.element),
"type": "h1",
"key": null,
"ref": null,
"props": {"children": "Hello World"},
"_owner": null,
"_store": {}
}
三.ReactDOM类
这个类包含渲染React Elements的工具方法,主要是 render()
, renderToString()
,
renderToStaticMarkup()
我们通过 ReactDOM.render()
将 React Elements及其children 渲染成 DOM,语法
ReactDOM.render(ReactElementToRender, Target)
例如:
var para = React.createElement("p", null, "this is a paragragh");
ReactDOM.render(para, document.body); // 将段落para添加到body中
// 即
This is paragragh
1.React渲染子元素使用 props.children
比如可以创建一个ul
React.createElement("ul", {"className": "navigation"},
React.createElement("li", null, "Home"),
React.createElement("li", null, "Images"),
React.createElement("li", null, "Videos"),
React.createElement("li", null, "Maps")
)
// 创建的对象字面量为:
{
"type": "ul",
"props": {
"children": [
{"type": "li", "props": {"children": "Home"}},
{"type": "li", "props": {"children": "Images"}},
{"type": "li", "props": {"children": "Videos"}},
{"type": "li", "props": {"children": "Maps"}}
]
}
...
}
注意上面的"className"为html中的class特性, 因为"class"是javascript保留关键词,避免冲突
2.构建带数据的React Elements
使用React的一大好处就是分离UI元素和数据,上面的例子可以写为:
const items = [
"Home",
"Images",
"Videos",
"Maps"
];
React.createElement(
"ul",
{"className": "navigation"},
items.map(item => React.createElement("li", null, item))
);
渲染之后运行上面的代码浏览器会报出一个错误:Each child in an array or iterator should have an unique "key" prop.
key property 用于帮助React 高效的更新DOM
上面可以写为:
React.createElement(
"ul",
{"className": "navigation"},
items.map((item, i) => React.createElement("li", {key: i}, item))
);
// 这样就不会报错了
四.React Components
每一个用户界面(UI)都由各个零件(parts)组成,在React中我们称这些Parts为 Components,创建组件有3种方法:
- React.createClass({});
- ES6 class继承的方法;
- stateless functional components
1.React.createClass()
我们能在这个方法中引用 this
,指向组件实例,属性能够通过 this.props
来访问
const nav = React.createClass({
displayName: "navigation", // 组件的显示名称
render() {
return React.createElement("ul", {"className": "navigation"},
React.createElement("li", null, "Home"),
React.createElement("li", null, "Images"),
React.createElement("li", null, "Videos"),
React.createElement("li", null, "Maps")
}
});
// 通过组件来创建 React元素
const list = React.createElement(nav, null, null);
ReactDOM.render(list, document.getElementById("container"));
数据可以通过属性的方式React组件中:
const items = [
"Home",
"Images",
"Videos",
"Maps"
];
const nav = React.createClass({
displayName: "navigation",
render() {
return React.createElement(
"ul",
{"className": "navigation"},
this.props.items.map(
(item, i) =>
React.createElement("li", {key: i}, item)
)
);
}
});
// 通过组件来创建 React元素, 注意items作为属性传入
const list = React.createElement(nav, {items}, null);
// 渲染
ReactDOM.render(list, document.getElementById("container"));
可以通过Ract developer tools 查看组件:
- Home
- Images
- Videos
- Maps
组件的本质是对象,以下表示方法是大多数 MVC 中 视图(VIEWS) 的表示方法, 即将方法分离出来
const nav = React.createClass({
displayName: "navigation",
// 单独将方法提出来
renderList(item, i) {
return React.createElement("li", {key: i}, item)
},
render() {
return React.createElement(
"ul",
{"className": "navigation"},
// 引用对象中的其他方法
this.props.items.map(this.renderList)
);
}
});
2.抽象类React.Component, 使用ES6语法
我们可以通过继承的方法来创建自定义组件
class MyComponent extends React.Component {
renderList(item, i) {
return React.createElement("li", {key: i}, item)
},
render() {
return React.createElement(
"ul",
{"className": "navigation"},
this.props.items.map(this.renderList)
);
}
}
3.无状态函数组件
Stateless functional components are functions not objects, 因此它没有 this 作用域。有以下几个特定:
- 它们是简单的纯函数,应用中更多的使用,除非有其他要求要使用React.createClass,或继承
- 函数接受 properties, 返回 一个DOM
- 这是函数编程的一种实践;
- 要引用 this 时则不能使用无状态函数组件
比如上面的例子可以写为:
const nav = props =>
React.createElement("ul", {"className": "navigation"},
props.items.map(
(item, i) =>
React.createElement("li", {key: i}, item)
)
)
其他渲染步骤和上面的都一样。
可以通过参数解构的方法改写上面的函数:
const nav = ({items}) => // 主要对象的解构这个地方要添加括号
React.createElement("ul", {"className": "navigation"},
items.map(
(item, i) =>
React.createElement("li", {key: i}, item)
)
)
// 上面的解构为
let {items} = props;
4.ReactDOM 渲染的优点
ReactDOM渲染如果DOM解构有变化,只更新变化部分,而不是全部重新加载,重新渲染,这样很大的优化了性能
五.Factories
这是另一种创建React Elements 的方法,可以通过React.createFactory
1.React.DOM.ElementType
这种方法用于创建 HTML 类型的 React 元素:
React.DOM.ul({"className": "navigation"},
React.DOM.li(null, "Home"),
React.DOM.li(null, "Home"),
React.DOM.li(null, "Home"),
React.DOM.li(null, "Home")
);
当然这也可以添加数据的方式:
const items = [
"Home",
"Images",
"Videos",
"Maps"
];
const list = React.DOM.ul({"className": "navigation"},
items.map((item, i) =>
React.DOM.li({key: i}, item)
)
);
ReactDOM.render(
list,
document.getElementById("container")
)
2.调用组件作为函数
React.createFactory() 快速将一个组件渲染成一个React Element
const {render} = ReactDOM; // 解构
const items = [
"Home",
"Images",
"Videos",
"Maps"
];
// 无状态函数组件
const list => ({items}) =>
React.createElement(
"ul",
{"className": "navigation"}
items.map((item, i) =>
React.createElement("li", {key: i}, ite,)
)
)
// 快速将一个组件渲染成React Element
// myList 变为一个函数,接受 属性 和 子元素 作为参数
const myList = React.createFactory(list);
// 渲染
render(
myList({items}),
document.getElementById("container")
)
如果不使用 JSX 的话,会发现工厂(factories)方法比反复的书写React.createElement方便;但是如果JSX, 将会发现永远不会使用工厂方法, 下一章将会通过 JSX TAG 来创建 React Elements
总结
通过上面的介绍,我们应该能掌握以下几点:
- 掌握 React Elements 是什么
- ReactDOM类工具, 如何将一个React元素渲染成 DOM元素
- React Components 和 React Elements之间的联系, 如何将React组件转变成React元素,然后再渲染成DOM元素, 书写组件的几种方法
- 分离数据与UI的写法
- 常用方法有:
- React.createElement(ElementType, props, children);
- ReactDOM.render(reactElement, target);
- React.createClass(obj);
- React.DOM.HTMLElementType(prop, children);
- React.createFactory(reactComponent)