什么是JSX?
JSX is an embeddable XML-like syntax extension to JavaScript without any defined semantics.
JSX
是一种类XML
语言,是JavaScript
的语法扩展,全称是JavaScript XML
。JSX
并不是由引擎或浏览器来实现,也并不打算并入到ECMAScript
标准规范中,它旨在被各种预处理器转换成标准的ECMAScript
语法。正如前面所说,JSX
就像XML
一样,它定义有自己的标签名、属性、子元素,需要注意的是,如果属性的值在大括号内,会当作JavaScript
表达式处理,如果在引号内,则会当作字符串类型(String)处理。
首先,看一个简单的示例,使用JSX
来表示一个UI下拉选项框组件:
为什么要学习JSX?
由于最近在学习 React,而官方是推荐使用JSX
来编写其组件,从技术角度来说,React
可以不使用JSX
来编写组件,但是使用JSX
可以让代码可读性更高、语义更清晰、对React
元素进行抽象。基于此,结合对React
的学习需求,还是很有必要先学习并掌握JSX
的使用,并且学习成本也相对较低,只要了解其语法规则就可以使用了。
JSX的语法规范
JSX标签
自闭合标签
如果标签没有子元素,可以使用自闭合标签:< JSXElementName JSXAttributesopt / >123<div className="sidebar" /><MyCounter color="blue" count='{3 + 5}' /><Scoreboard className="results" scores={gameScores} />开/闭标签
也可以写成开/闭标签的形式:< JSXElementName JSXAttributesopt > </ JSXElementName >123const element1 = <h1 className="red">Hello, world!</h1>;const element2 = <img src={user.avatarUrl}></img>;const element3 = <div tabIndex="0">{user.title}</div>;如果属性的值在引号内,会当作字符串类型(String)处理,如果属性值是在大括号内,则会当作
JavaScript
表达式处理。
JSX元素名
JSX
的元素名可是一个标识符、命名空间和成员表达式:
JSX属性
JSX
属性有一般属性、展开属性:JSXAttribute JSXAttributesopt 、{ … AssignmentExpression } 。
属性的值可以用双引号("string"
)、单引号('string'
)和大括号({expression}
),需要注意的是,如果属性值使用了单/双引号,该字符串值内部就不能再出现相对应的引号了。
JSX子元素
String字面值(String Literals)
可以直接写字符串类型或HTML格式:12<MyComponent>Hello world!</MyComponent><div>This is valid HTML & JSX at the same time.</div>JSX子组件
1234<MyContainer><MyFirstComponent /><MySecondComponent /></MyContainer>JavaScript表达式
比如稍微复杂一点的表达式,包括一些取值、方法调用和类型转换的场景:123456789101112<ul>{todos.map((message) => <Item key={message} message={message} />)}</ul><Repeat numTimes={10}>{(index) => <div key={index}>This is item {index} in the list</div>}</Repeat><div>Hello {props.addressee}!My JavaScript variable is {String(myVariable)}.</div>
在React中使用JSX
JSX命名规则
在使用JSX
编写React
时,针对HTML
标签,保留原来的关键字和命名规则,即全部字母小写,而对于自定义的组件(Component),需要遵循首字母大写的约定。由于JSX
相对于HTML
更接近于JavaScript
,对于所有的DOM属性及事件处理器,都应该使用camelCased(骆峰命名)与标准的JavaScript
风格保持一致,如:
因为class
和for
是JavaScript
的保留字,内建 DOM nodes 的JSX
元素应该分别使用属性名className
和htmlFor
,另外,如tabindex
也应写成tabIndex
。
而自定义的JSX
元素可以直接使用class
和for
。
JSX命名空间组件
如果你正在构建一个有很多子组件的组件,比如表单,你也许会最终得到许多的变量声明,比如以下不太友好的代码块。
为了使其更简单和容易,命名空间组件令你使用包含其他组件作为属性的单一的组件,通过使用点符号.
很方便地在一个组件上表示多个成员组件,使得在语法结构上更加清晰。
JavaScript表达式
属性表达式
对于属性表达式,之前已经在语法规范中提到过了,要使用JavaScript
表达式作为属性值,只需把这个表达式用一对大括号({}
)包起来即可。1var person = <Person name={window.isLoggedIn ? window.name : ''} />;Boolean属性
对于Boolean属性,省略一个属性的值会导致JSX
把它当做true
,要传值false
必须使用属性表达式,通常会出现于使用HTML
表单元素,含有属性如disabled
,required
,checked
和readOnly
。1234567// 在JSX中,对于禁用按钮这二者是相同的<input type="button" disabled />;<input type="button" disabled={true} />;// 在JSX中,对于不禁用按钮这二者是相同的<input type="button" />;<input type="button" disabled={false} />;子节点表达式
对于子节点表达式,同样可以在大括号内表示,比如<Nav />
和<Login />
。1var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;如何添加注释
JSX
里添加注释很容易,它们只是JavaScript
表达式而已,但需要小心的是,当在一个标签的子节点块时,要用{}
包围要注释的部分。1234567891011var content = (<Nav>{/* child comment, 用 {} 包围 */}<Person/* 多行注释 */name={window.isLoggedIn ? window.name : ''} // 行尾注释/></Nav>);
JSX DOM陷阱
自定义HTML属性
React
不显示HTML
规范里不存在的元素属性,若需要使用自定义属性,要加data-
前缀。1<div data-custom-attribute="foo" />而在自定义元素中任意的属性都是被支持的(在标签名里带有连接符或
is="..."
属性的)。1<x-my-component custom-attribute="foo" />以
aria-
开头的网络无障碍属性可以正常使用。1<div aria-hidden={true} />HTML实体
HTML
实体可以插入到JSX
的文本中,如果想在JSX
表达式中显示HTML
实体,会遇到二次转义的问题,因为React
默认会转义所有字符串,为了防止各种 XSS 攻击。1234// 正确,可以正常解析HTML<div>First · Second</div>// 错误,不能解析,会直接显示“First · Second”<div>{'First · Second'}</div>但可以通过使用Unicode字符解决,但需要确保文件是UTF-8编码,且网页也指定为UTF-8编码。
12<div>{'First \u00b7 Second'}</div><div>{'First ' + String.fromCharCode(183) + ' Second'}</div>可以在数组里混合使用字符串和
JSX
元素。1<div>{['First ', <span>·</span>, ' Second']}</div>
JSX运行与安全
JSX
在运行时被加载元素类型,因此,元素类型不能是表达式,以下是错误的示例:
但可以定义变量,但首字母须大写,如下格式是正确的示例:
JSX
可以防止注入攻击,在React DOM
中,默认在渲染前会转义在JSX
中的所有值,因此,可以保证不会被注入攻击,所有的内容都已经被转换为字符串进行渲染,同进也会防止跨站脚本攻击(XSS)。
小结
主要对JSX
的基本概念、语法规范、在React
中使用等方面进行了介绍并举例,在React
中用法主要包括JSX
命名规则、命名空间组件、JavaScript
表达式、DOM陷阱以及运行与安全方面的介绍和示例。
通常,建议在你的编辑器中配置Babel
语法体系,从而使得ES6
和JSX
代码都可以高亮显示。另外,可以到在线的 JS BIN 或 Babel REPL 进行简单练习。
References