React躬行记(2)——JSX
JSX既不是字符串,也不是HTML,而是一种类似XML,用于描述用户界面的JavaScript扩展语法,如下代码所示。在使用JSX时,为了避免自动插入分号时出现问题,推荐在其最外层用圆括号包裹,并且必须用一个元素包裹(例如下面的<div>元素)其它元素或文本,所有的元素还必须得闭合。
(<div>
<input type="text" text={getName()} />
<button className="btn">搜索</button>
</div>)
JSX为视图和数据架起了一座沟通的桥梁,它看起来与模板语言类似,但没有创造新的模板语法,因为JSX最终会被编译成普通的JavaScript对象,所以能够直接使用JavaScript语法。
一、元素
JSX中的元素称为React元素,分为两种类型:DOM元素和组件元素,前者对应原生的HTML元素,标签的首字母要小写;后者对应自定义元素,标签的首字母要大写,如下所示。
<button>提交</button>; //DOM元素
<Btn>自定义按钮</Btn>; //组件元素
1)React.createElement()
无论是DOM元素还是组件元素,最终都会通过Babel编译器将它们转换成React.createElement()方法的调用,例如下面的<button>元素。
<button className="btn">搜索</button>
//编译成
React.createElement(button, { className: "btn" }, "搜索");
React.createElement()能接收3个参数(如下所示),其中type是元素类型,也就是它的名称;props是一个由元素属性组成的对象;children是它的子元素(即内容),可以是文本也可以是其它元素。
React.createElement(type, [props], [...children])
方法的返回值是一个元素对象,简化过的对象如下所示。
{
type: "button",
props: {
className: "btn",
children: "搜索"
}
}
为了避免在多人协作时出现相同名称的元素,可以为元素添加命名空间,例如调用UI模块中的Btn元素,可以像下面这么写。
const UI = {
Btn: function(props) {
return <button className={props.className}>{props.children}</button>;
}
}
<UI.Btn className="btn">搜索</UI.Btn>
2)注释
JSX中的注释需要像下面这样,用一对花括号、斜杠和星号包裹。
{/* 表单中的提交按钮 */}
<button>提交</button>
3)表达式
在JSX的任意位置都能插入表达式,但必须用花括号包裹住才能有效,例如像下面这样调用getName()函数。注意,在JSX中不能插入语句。
function getName() {
return "strick";
}
<div>{getName()}</div>
由于JSX本身就是一种表达式,因此它可以作为函数的参数、返回值或变量的值,如下所示。
if (true) {
let fragment = <div>{getName()}</div>;
}
在JSX中传入的值都会自动被HTML转义,这样可以防止XSS攻击,例如输入“<p></p>”,输出“<p></p>”,如下所示。
//<p></p>
<div>{"<p></p>"}</div>
如果要输出不转义的值,那么可以用React提供的dangerouslySetInnerHTML属性,如下代码所示。它的值是一个包含__html属性的对象,其作用相当于调用DOM元素的innerHTML属性。
<div dangerouslySetInnerHTML={{__html: "<p></p>"}}></div>
4)内容
当元素的内容是字符串时,JSX会移除字符串中的空行,其内部的换行会被替换成一个空格,下面的两个元素是等价的。
<p>freedom strick</p>
<p>
freedom strick
</p>
当元素的内容是false、null、undefined或true时,它们都不会被渲染到DOM结构中,因此下面的五个元素是等价的。
<p></p>
<p>{false}</p>
<p>{null}</p>
<p>{undefined}</p>
<p>{true}</p>
5)渲染
如果要将React元素渲染到页面的DOM结构中,可以调用ReactDOM.render()方法,此方法接收3个参数,如下所示。
ReactDOM.render(element, container[, callback])
element是要渲染的元素;container是页面中的一个节点,在此处起到容器的作用,element会被渲染到container中;callback是可选的回调函数,会在组件被渲染或更新之后触发。此方法的使用可参考下面的示例。
<div id="container">freedom</div>
<script type="text/babel">
ReactDOM.render(
<p>strick</p>,
document.getElementById("container")
);
</script>
当第一次调用ReactDOM.render()方法时,容器内部的元素会被全部替换掉,也就是执行上面的代码得到的结果如下所示,原先的字符串“freedom”被替换成了<p>元素。
<div id="container">
<p>strick</p>
</div>
二、属性
React对元素属性进行了一次封装,不仅规范了属性的命名,还完善了浏览器的兼容性。在JSX中,DOM元素的属性对应标准的DOM属性和特性;而组件元素的属性都是无对应关系的自定义属性。除了以“data-”和“aria-”为前缀的元素属性要用小写命名之外,其余的都得遵循小驼峰命名法,例如maxlength变成maxLength、onclick变成onClick等。还有两个比较特殊的属性:class和for,由于它们是JavaScript的关键字,因此需要变成className和htmlFor后才能使用。
1)默认值
属性的默认值是true,下面的两个元素是等价的,页面上的显示如图1所示。
<input type="text" value />
<input type="text" value={true} />

图 1 带默认值的文本框
在标准的DOM中,诸如checked、disabled等布尔属性,它们的值要么为空要么为对应的关键字,例如“checked”、“disabled”;而JSX中的布尔属性,它们的值只能是true或false。
2)字符串和表达式
当属性的值是字符串时,其值需要用双引号包裹;当属性的值是表达式时,其值需要用花括号包裹,如下所示。
<input type="text" value="3" />
<input type="text" value={1 + 2} />
3)扩展属性
如果存在一个由元素属性组成的属性对象,那么就能利用ES6新增的扩展运算符,把属性对象展开并传递给元素,如下所示。
var props = { type: "text", value: "1" };
<input {...props} />
//相当于
<input type="text" value="1" />
相比直接在元素上设置属性,这种方式操作起来更加灵活。
三、虚拟DOM
HTML文档能被抽象成一棵由多种类型的节点构成的DOM树,而每次对DOM节点执行增删改查等操作,往往会触发非常消耗性能的重绘和重排。为了解决这个性能瓶颈,React引入了虚拟DOM。虚拟DOM(Virtual DOM)是构建在真实DOM之上的一层抽象,它将DOM元素映射成内存中的JavaScript对象(即通过React.createElement()得到的React元素),形成一棵JavaScript对象树。
在React中,将虚拟DOM转换成真实DOM的过程叫做调和(Reconciliation),而diff算法是保证调和高效的关键,因为diff算法会找出新旧虚拟DOM之间的差异部分,随后只更新真实DOM中需要变化的节点,而不是将整棵DOM树重新渲染一遍。经过虚拟DOM的隔离,开发人员已经不用再直接与页面上的真实DOM打交道了,如图2所示。

图 2 新的开发模式
虚拟DOM还有一大亮点,那就是将它与其他渲染器配合能够集成到指定的终端,即将React元素映射成对应的原生控件,前文所描述的是用react-dom在Web端渲染,还可以使用react-native在手机端(Android或iOS)渲染。
React躬行记(2)——JSX的更多相关文章
- React躬行记(8)——样式
由于React推崇组件模式,因此会要求HTML.CSS和JavaScript混合在一起,虽然这与过去的关注点分离正好相反,但是更有利于组件之间的隔离.React已将HTML用JSX封装,而对CSS只进 ...
- React躬行记(5)——React和DOM
React实现了一套与浏览器无关的DOM系统,包括元素渲染.节点查询.事件处理等机制. 一.ReactDOM 自React v0.14开始,官方将与DOM相关的操作从React中剥离,组成单独的rea ...
- React躬行记(6)——事件
React在原生事件的基础上,重新设计了一套跨浏览器的合成事件(SyntheticEvent),在事件传播.注册方式.事件对象等多个方面都做了特别的处理. 一.注册事件 合成事件采用声明式的注册方式, ...
- React躬行记(3)——组件
组件(Component)由若干个React元素组成,包含属性.状态和生命周期等部分,满足独立.可复用.高内聚和低耦合等设计原则,每个React应用程序都是由一个个的组件搭建而成,即组成React应用 ...
- React躬行记(16)——React源码分析
React可大致分为三部分:Core.Reconciler和Renderer,在阅读源码之前,首先需要搭建测试环境,为了方便起见,本文直接采用了网友搭建好的环境,React版本是16.8.6,与最新版 ...
- React躬行记(4)——生命周期
组件的生命周期(Life Cycle)包含三个阶段:挂载(Mounting).更新(Updating)和卸载(Unmounting),在每个阶段都会有相应的回调方法(也叫钩子)可供选择,从而能更好的控 ...
- React躬行记(7)——表单
表单元素是一类拥有内部状态的元素,这些状态由其自身维护,通过这类元素可让用户与Web应用进行交互.HTML中的表单元素(例如<input>.<select>和<radio ...
- React躬行记(9)——组件通信
根据组件之间的嵌套关系(即层级关系)可分为4种通信方式:父子.兄弟.跨级和无级. 一.父子通信 在React中,数据是自顶向下单向流动的,而父组件通过props向子组件传递需要的信息是组件之间最常见的 ...
- React躬行记(10)——高阶组件
高阶组件(High Order Component,简称HOC)不是一个真的组件,而是一个没有副作用的纯函数,以组件作为参数,返回一个功能增强的新组件,在很多第三方库(例如Redux.Relay等)中 ...
随机推荐
- 深入理解ArrayList与LinkedList的区别
一.先来看看ArrayList与LinkedList 在JDK中所在的位置 从图中可以看出,ArrayList与LinkedList都是List接口的实现类,因此都实现了List的所有未实现的方法,只 ...
- 【cocos2d-js官方文档】五、Cocos2d-JS v3.0的新Action API
新增action中的方法 曾经,当我们须要反复一个action的时候,我们须要: sprite.runAction(cc.Repeat.create(action, 2)); 上面代码中创建了一个新的 ...
- lua转换etcd应答
local function decodeNodes(nodes) local table = {} for _, value in ipairs(nodes) do if value.nodes t ...
- JS数组操作:去重,交集,并集,差集
原文:JS数组操作:去重,交集,并集,差集 1. 数组去重 方法一: function unique(arr) { //定义常量 res,值为一个Map对象实例 const res = new Map ...
- ‘3 sigma’rule(68–95–99.7 rule)
不限标准正太分布,任一正太分布(normal distribution)均可. 围绕均值附近求得的区间概率: (μ−k⋅σ,μ+k⋅σ) Pr(μ−σ≤x≤μ+σ)≈0.6827Pr(μ−2σ≤x≤μ ...
- Plugin execution not covered by lifecycle configuration
Eclipse 环境 在工作空间 \.metadata\.plugins\org.eclipse.m2e.core\ 目录下 增加 lifecycle-mapping-metadata.xml 文件 ...
- Angular语法(三)——数据绑定
绑定类型 绑定类型可以按照数据流的方向分为三类:从源到视图,从视图到源,以及双向序列 示例 <!-- Bind button disabled state to `isUnchanged` pr ...
- wpf采用Xps实现文档显示、套打功能
原文:wpf采用Xps实现文档显示.套打功能 近期的一个项目需对数据进行套打,用户要求现场不允许安装office.页面预览显示必须要与文档完全一致,xps文档来对数据进行处理.Wpf的Document ...
- WCF Rest用法
GET GET单参数 服务器 [OperationContract] string GetOneParameter(string value); [WebInvoke(Method = "G ...
- XF 列表视图事件
<?xml version="1.0" encoding="utf-8" ?><ContentPage xmlns="http:// ...