JSX
是快速生成react
元素的一种语法,实际是React.createElement(component, props, ...children)
的语法糖,同时JSX
也是Js
的语法扩展,包含所有Js
功能。
在之前,Facebook
是PHP
大户,所以React
最开始的灵感就来自于PHP
。
在2004
年这个时候,大家都还在用PHP
的字符串拼接来开发网站。
这种方式代码写出来不好看不说,还容易造成XSS
等安全问题。应对方法是对用户的任何输入都进行转义Escape
,但是如果对字符串进行多次转义,那么反转义的次数也必须是相同的,否则会无法得到原内容,如果又不小心把HTML
标签给转义了,那么HTML
标签会直接显示给用户,从而导致很差的用户体验。
到了2010
年,为了更加高效的编码,同时也避免转义HTML
标签的错误,Facebook
开发了XHP
。XHP
是对PHP
的语法拓展,它允许开发者直接在PHP
中使用HTML
标签,而不再使用字符串。
这样的话,所有HTML
标签都使用不同于PHP
的语法,我们可以轻易的分辨哪些需要转义哪些不需要转义。不久的后来,Facebook
的工程师又发现他们还可以创建自定义标签,而且通过组合自定义标签有助于构建大型应用。
到了2013
年,前端工程师Jordan Walke
向他的经理提出了一个大胆的想法:把XHP
的拓展功能迁移到Js
中,首要任务是需要一个拓展来让Js
支持XML
语法,该拓展称为JSX
。因为当时由于Node.js
在Facebook
已经有很多实践,所以很快就实现了JSX
。
React
认为渲染逻辑本质上与其他UI
逻辑内在耦合,比如在UI
中需要绑定处理事件、在某些时刻状态发生变化时需要通知到UI
,以及需要在UI
中展示准备好的数据。
React
并没有采用将标记与逻辑进行分离到不同文件这种人为地分离方式,而是通过将二者共同存放在称之为组件的松散耦合单元之中,来实现关注点分离。
React
不强制要求使用JSX
,但是大多数人发现,在JavaScript
代码中将JSX
和UI
放在一起时,会在视觉上有辅助作用,它还可以使React
显示更多有用的错误和警告消息。
简单来说,JSX
可以很好的描述页面html
结构,很方便的在Js
中写html
代码,并具有Js
的全部功能。
JSX
的优点主要体现在以下三点:
JSX
执行更快,因为它在编译为JavaScript
代码后进行了优化。JavaScript
相比,JSX
是静态类型的,大多是类型安全的。使用JSX
进行开发时,应用程序的质量会变得更高,因为在编译过程中会发现许多错误,它也提供编译器级别的调试功能。JSX
中定义了一些规则以及用法:
JSX
只能有一个根元素,JSX
标签必须是闭合的,如果没有内容可以写成自闭和的形式<div />
。JSX
通过{}
嵌入Js
表达式。JSX
会被babel
转换成React.createElement
的函数调用,调用后会创建一个描述HTML
信息的Js
对象。JSX
中的子元素可以为字符串字面量。JSX
中的子元素可以为JSX
元素。JSX
中的子元素可以为存储在数组中的一组元素。JSX
中的子元素可以为Js
表达式,可与其他类型子元素混用;可用于展示任意长度的列表。JSX
中的子元素可以为函数及函数调用。JSX
中的子元素如果为boolean/null/undefined
将会被忽略,如果使用&&
运算符,需要确保前面的是布尔值,如果是0/1
则会被渲染出来。React
组件,可以使用object
的点语法使用该组件。React
元素会被转换为调用React.createElement
函数,参数是组件,因此React
和该组件必须在作用域内。React
元素需要大写字母开头,或者将元素赋值给大小字母开头的变量,小写字母将被认为是HTML
标签。React
元素类型,需要先将其赋值给大写字母开头的变量,再把该变量作为组件。在示例中我们声明了一个名为name
的变量,然后在JSX
中使用它,并将它包裹在大括号中。在JSX
语法中,可以在大括号内放置任何有效的JavaScript
表达式。例如2 + 2
、user.firstName
或formatName(user)
都是有效的JavaScript
表达式。
同样JSX
也是一个表达式,JSX
天生就是需要被编译之后才可以使用的,在编译之后JSX
表达式会被转为普通JavaScript
函数调用,并且对其取值后得到JavaScript
对象。也就是说,你可以在if
语句和for
循环的代码块中使用JSX
,将JSX
赋值给变量,把JSX
当作参数传入,以及从函数中返回JSX
。
通常可以通过使用引号来将属性值指定为字符串字面量,也可以使用大括号来在属性值中插入一个JavaScript
表达式,在属性中嵌入JavaScript
表达式时,不要在大括号外面加上引号。因为JSX
语法上更接近JavaScript
而不是HTML
,所以React DOM
使用camelCase
小驼峰命名来定义属性的名称,而不使用HTML
属性名称的命名约定。例如JSX
里的class
变成了className
,而tabindex
则变为tabIndex
。
JSX
中也可以使用</>
来闭合标签,另外JSX
同样也可以直接定义很多子元素。
你可以安全地在JSX
当中插入用户输入内容,React DOM
在渲染所有输入内容之前,默认会进行转义,这样可以确保在你的应用中,永远不会注入那些并非自己明确编写的内容,所有的内容在渲染之前都被转换成了字符串,可以有效地防止 XSS
跨站脚本攻击。
实际上Babel
会把JSX
转译成一个名为React.createElement()
函数调用,通过React.createElement()
定义的元素与使用JSX
生成的元素相同,同样这就使得JSX
天生就是需要编译的。
React.createElement()
会预先执行一些检查,以帮助你编写无错代码,但实际上它创建了一个这样的对象。这些对象被称为React 元素
,它们描述了你希望在屏幕上看到的内容,React
通过读取这些对象,然后使用它们来构建DOM
以及保持随时更新。
实际上,这就是虚拟DOM
的一个节点,Virtual DOM
是一种编程概念,在这个概念里,UI
以一种理想化的,或者说虚拟的表现形式被保存于内存中,并通过如ReactDOM
等类库使之与真实的DOM
同步,这一过程叫做协调。这种方式赋予了React
声明式的API
,您告诉React
希望让UI
是什么状态,React
就确保DOM
匹配该状态,这样可以从属性操作、事件处理和手动DOM
更新这些在构建应用程序时必要的操作中解放出来。
与其将Virtual DOM
视为一种技术,不如说它是一种模式,人们提到它时经常是要表达不同的东西。在React
的世界里,术语Virtual DOM
通常与React
元素关联在一起,因为它们都是代表了用户界面的对象,而React
也使用一个名为fibers
的内部对象来存放组件树的附加信息,上述二者也被认为是React
中Virtual DOM
实现的一部分,Virtual DOM
也为使用diff
算法奠定了基础。