这一节我们通过一个简单的例子讲解 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. MongoDB 自己定义函数

    定义 db.system.js.insert({ _id : "TestConcat", value : function TestConcat(s1, s2){ return s ...

  2. makefile redefinition or previous definition

    operation.h:4: error: redefinition of 'class operation' operation.h:5: error: previous definition of ...

  3. Codeforces 768 E. Game of Stones 博弈DP

    E. Game of Stones   Sam has been teaching Jon the Game of Stones to sharpen his mind and help him de ...

  4. 基于字符的打印机 图形化打印机 PostScript解释器

    60行*80字符/行=4800字节 300点/英寸(300DPI)   8*10英寸/页打印区域 光栅图像处理器  RIP PostScript程序--- > PostScript解释器 --& ...

  5. 设备没有可用空间 /var/spool/clientmqueue sendmail

    [root@hadoop3 /]# crontab -e/tmp/crontab.TB7A7w: 设备上没有空间[root@hadoop3 /]# df -Bg文件系统 1G-块 已用 可用 已用% ...

  6. 浅谈cookie 和session 的区别

    具体来说 cookie 是保存在“客户端”的,而session是保存在“服务端”的 cookie 是通过扩展http协议实现的 cookie 主要包括 :名字,值,过期时间,路径和域: 如果cooki ...

  7. scikit-learn 机器学习工具

    1.http://scikit-learn.org/stable/        官网:关于scikit-learn介绍等 2. http://stackoverflow.com/questions/ ...

  8. Masonry remake更新约束

    前言 说到iOS自动布局,有很多的解决办法.有的人使用xib/storyboard自动布局,也有人使用frame来适配.对于前者,笔者并不喜欢,也不支持.对于后者,更是麻烦,到处计算高度.宽度等,千万 ...

  9. [USACO 2017DEC] Barn Painting

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=5141 [算法] 树形DP 时间复杂度 : O(N) [代码] #include< ...

  10. NPU 2015年陕西省程序设计竞赛网络预赛(正式赛)F题 和谐的比赛(递推 ||卡特兰数(转化成01字符串))

    Description 今天西工大举办了一场比赛总共有m+n人,但是有m人比较懒没带电脑,另外的n个人带了电脑.不幸的是,今天机房的电脑全坏了只能用带的电脑,一台电脑最多两人公用,确保n>=m. ...