第1章 Pure React

Pure React

ReactReactDOM0.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种方法:

  1. React.createClass({});
  2. ES6 class继承的方法
  3. 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 作用域。有以下几个特定:

  1. 它们是简单的纯函数,应用中更多的使用,除非有其他要求要使用React.createClass,或继承
  2. 函数接受 properties, 返回 一个DOM
  3. 这是函数编程的一种实践;
  4. 要引用 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


总结

通过上面的介绍,我们应该能掌握以下几点:

  1. 掌握 React Elements 是什么
  2. ReactDOM类工具, 如何将一个React元素渲染成 DOM元素
  3. React Components 和 React Elements之间的联系, 如何将React组件转变成React元素,然后再渲染成DOM元素, 书写组件的几种方法
  4. 分离数据与UI的写法
  5. 常用方法有:
    • React.createElement(ElementType, props, children);
    • ReactDOM.render(reactElement, target);
    • React.createClass(obj);
    • React.DOM.HTMLElementType(prop, children);
    • React.createFactory(reactComponent)

你可能感兴趣的:(第1章 Pure React)