这一节我们通过一个简单的例子讲解 React.js 描述页面 UI 的方式。把 src/index.js 中的代码改成:

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './index.css' class Header extends Component {
render () {
return (
<div>
<h1>React 小书</h1>
</div>
)
}
} ReactDOM.render(
<Header />,
document.getElementById('root')
)

我们在文件头部从 react 的包当中引入了 React 和 React.js 的组件父类 Component。记住,只要你要写 React.js 组件,那么就必须要引入这两个东西。

ReactDOM 可以帮助我们把 React 组件渲染到页面上去,没有其它的作用了。你可以发现它是从 react-dom 中引入的,而不是从 react 引入。有些朋友可能会疑惑,为什么不把这些东西都包含在 react 包当中呢?我们稍后会回答这个问题。

接下来的代码你看起来会比较熟悉,但又会有点陌生。你看其实它跟我们前几节里面讲的内容其实很类似,一个组件继承 Component 类,有一个 render 方法,并且把这个组件的 HTML 结构返回;这里 return 的东西就比较奇怪了,它并不是一个字符串,看起来像是纯 HTML 代码写在 JavaScript 代码里面。你也许会说,这不就有语法错误了么?这完全不是合法的 JavaScript 代码。这种看起来“在 JavaScript 写的标签的”语法叫 JSX。

JSX 原理

为了让大家深刻理解 JSX 的含义。有必要简单介绍了一下 JSX 稍微底层的运作原理,这样大家可以更加深刻理解 JSX 到底是什么东西,为什么要有这种语法,它是经过怎么样的转化变成页面的元素的。

思考一个问题:如何用 JavaScript 对象来表现一个 DOM 元素的结构,举个例子:

<div class='box' id='content'>
<div class='title'>Hello</div>
<button>Click</button>
</div>

每个 DOM 元素的结构都可以用 JavaScript 的对象来表示。你会发现一个 DOM 元素包含的信息其实只有三个:标签名,属性,子元素。

所以其实上面这个 HTML 所有的信息我们都可以用合法的 JavaScript 对象来表示:

{
tag: 'div',
attrs: { className: 'box', id: 'content'},
children: [
{
tag: 'div',
arrts: { className: 'title' },
children: ['Hello']
},
{
tag: 'button',
attrs: null,
children: ['Click']
}
]
}

你会发现,HTML 的信息和 JavaScript 所包含的结构和信息其实是一样的,我们可以用 JavaScript 对象来描述所有能用 HTML 表示的 UI 信息。但是用 JavaScript 写起来太长了,结构看起来又不清晰,用 HTML 的方式写起来就方便很多了。

于是 React.js 就把 JavaScript 的语法扩展了一下,让 JavaScript 语言能够支持这种直接在 JavaScript 代码里面编写类似 HTML 标签结构的语法,这样写起来就方便很多了。编译的过程会把类似 HTML 的 JSX 结构转换成 JavaScript 的对象结构。

上面的代码:

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './index.css' class Header extends Component {
render () {
return (
<div>
<h1 className='title'>React 小书</h1>
</div>
)
}
} ReactDOM.render(
<Header />,
document.getElementById('root')
)

经过编译以后会变成:

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './index.css' class Header extends Component {
render () {
return (
React.createElement(
"div",
null,
React.createElement(
"h1",
{ className: 'title' },
"React 小书"
)
)
)
}
} ReactDOM.render(
React.createElement(Header, null),
document.getElementById('root')
);

React.createElement 会构建一个 JavaScript 对象来描述你 HTML 结构的信息,包括标签名、属性、还有子元素等。这样的代码就是合法的 JavaScript 代码了。所以使用 React 和 JSX 的时候一定要经过编译的过程。

这里再重复一遍:所谓的 JSX 其实就是 JavaScript 对象。每当在 JavaScript 代码中看到这种 JSX 结构的时候,脑子里面就可以自动做转化,这样对你理解 React.js 的组件写法很有好处。

有了这个表示 HTML 结构和信息的对象以后,就可以拿去构造真正的 DOM 元素,然后把这个 DOM 元素塞到页面上。这也是我们最后一段代码中 ReactDOM.render 所干的事情:

ReactDOM.render(
<Header />,
document.getElementById('root')
)

ReactDOM.render 功能就是把组件渲染并且构造 DOM 树,然后插入到页面上某个特定的元素上(在这里是 id 为 root 的 div 元素)。

所以可以总结一下从 JSX 到页面到底经过了什么样的过程:

有些同学可能会问,为什么不直接从 JSX 直接渲染构造 DOM 结构,而是要经过中间这么一层呢?

第一个原因是,当我们拿到一个表示 UI 的结构和信息的对象以后,不一定会把元素渲染到浏览器的普通页面上,我们有可能把这个结构渲染到 canvas 上,或者是手机 App 上。所以这也是为什么会要把 react-dom 单独抽离出来的原因,可以想象有一个叫 react-canvas 可以帮我们把 UI 渲染到 canvas 上,或者是有一个叫 react-app 可以帮我们把它转换成原生的 App(实际上这玩意叫 ReactNative)。

第二个原因是,有了这样一个对象。当数据变化,需要更新组件的时候,就可以用比较快的算法操作这个 JavaScript 对象,而不用直接操作页面上的 DOM,这样可以尽量少的减少浏览器重排,极大地优化性能。这个在以后的章节中我们会提到。

总结

要记住几个点:

  1. JSX 是 JavaScript 语言的一种语法扩展,长得像 HTML,但并不是 HTML。
  2. React.js 可以用 JSX 来描述你的组件长什么样的。
  3. JSX 在编译的时候会变成相应的 JavaScript 对象描述。
  4. react-dom 负责把这个用来描述 UI 信息的 JavaScript 对象变成 DOM 元素,并且渲染到页面上。

下一节:组件的 render 方法

上一节:React.js 基本环境安装

使用 JSX 描述 UI 信息的更多相关文章

  1. React.js 小书 Lesson6 - 使用 JSX 描述 UI 信息

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson6 转载请注明出处,保留原文链接和作者信息. 这一节我们通过一个简单的例子讲解 React.j ...

  2. SQL Server2000导出数据时包含主键、字段默认值、描述等信息

    时经常用SQL Server2000自带的导出数据向导将数据从一台数据库服务器导出到另一台数据库服务器: 结果数据导出了,但表的主键.字段默认值.描述等信息却未能导出,一直没想出什么方法,今天又尝试了 ...

  3. 使用静态资源设置UI信息

    首先建立一个文件存放样式设置(资源字典),所有风格设置都可以这里进行 加入以下代码: <ResourceDictionary xmlns="http://schemas.microso ...

  4. React.js 小书介绍

    React.js 小书 Github 关于作者 这是一本关于 React.js 的小书. 因为工作中一直在使用 React.js,也一直以来想总结一下自己关于 React.js 的一些知识.经验.于是 ...

  5. 组件的 render 方法

    React.js 中一切皆组件,用 React.js 写的其实就是 React.js 组件.我们在编写 React.js 组件的时候,一般都需要继承 React.js 的 Component(还有别的 ...

  6. React.js 基本环境安装

    安装 React.js React.js 单独使用基本上是不可能的事情.不要指望着类似于 jQuery 下载放到 <head /> 标签就开始使用.使用 React.js 不管在开发阶段生 ...

  7. 【React.js小书】动手实现 React-redux(五):Provider - 方志

    我们要把 context 相关的代码从所有业务组件中清除出去,现在的代码里面还有一个地方是被污染的.那就是 src/index.js 里面的 Index: 1234567891011121314151 ...

  8. react中的jsx详细理解

    这是官网上的一个简单的例子 const name = 'Josh Perez'; const element = <h1>Hello, {name}</h1>; ReactDO ...

  9. React从入门到放弃之前奏(2):React简介

    本系列将尽可能使用ES6(ES2015)语法.所以均在上节webpack的基础上做开发. React是Facebook开发的一款JS库,因为基于Virtual DOM,所以响应速度快,以及支持跨平台. ...

随机推荐

  1. IIS 配置 FTP 网站 H5 音频标签自定义样式修改以及添加播放控制事件

    IIS 配置 FTP 网站   在 服务器管理器 的 Web服务器IIS 上安装 FTP 服务 在 IIS管理器 添加FTP网站 配置防火墙规则 说明:服务器环境是Windows Server 200 ...

  2. BZOJ 3550 ONTAK2010 Vacation 单纯形

    题目大意:给定一个长度为3n的区间.要求选一些数,且随意一段长度为n的区间内最多选k个数.求选择数的和的最大值 单纯形直接搞 注意一个数仅仅能被选一次 因此要加上xi<=1这个约束条件 不明确3 ...

  3. java反射(2)+Class.forName( )

    在上一篇文章中说说java反射(1)我们已经了解了反射的基本概念以及它的原理,但是我们知道反射只能能用它来做些什么呢? 其实在我们很多已经很熟的框架中都有它的身影,例如Hibernate框架中的关联映 ...

  4. HDU1255 覆盖的面积 —— 求矩形交面积 线段树 + 扫描线 + 离散化

    题目链接:https://vjudge.net/problem/HDU-1255 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input输入数据的第一行是一个正整数T(1<= ...

  5. YTU 2918: Shape系列-4

    2918: Shape系列-4 时间限制: 1 Sec  内存限制: 128 MB 提交: 276  解决: 232 题目描述 小聪送给小亮和小华的形状他们都很喜欢,小亮和小华非要比一下他们两个的形状 ...

  6. Ubuntu linux 返回上一次访问的目录

    cd - (cd空格 减号)返回最近一次访问的目录 这个非常方便.平时经常用终端切换目录,能够方便地回到原来的目录就很爽了. jiqing@jiqing-pad:/usr/local/redis/sr ...

  7. jQuery简单纯文字提示条

    如何制作jQuery简单纯文字提示条,先介绍提示条(tooltip)的意思是用户鼠标悬停经过事件发生提示title.它们已经呈现在大多数浏览器中,当你可以提供一个链接或图片的title属性,就是用户将 ...

  8. uCos-III移植到STM32F10x

    最近在百度上看了uCOS-III 的介绍后,诸多功能有很大的提升和改进,感觉有必要升级一下开发环境.百度介绍:http://baike.baidu.com/view/8531313.htm 环境: S ...

  9. java面试(上)

    http://blog.csdn.net/jackfrued/article/details/44921941 1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: - 抽象:抽象是 ...

  10. python 面向对象十 __init__和__new__

    一.__init__和__new__方法 __init__ 和 __new__ 最主要的区别在于:1.__init__ 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的 ...