深入了解JSX
特别声明:为了感谢社区对W3cplus的支持,在毕业季到来之际,小站开启毕业季优惠,在2019年07月01日至2019年07月10日之间,年费价格为 ¥299.00元。如果您喜欢小站的内容,可以点击开通会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!(^_^)
最近开始学着使用React写东西。在写代码时会使用JSX,不了解JSX的相关知识写起代码的效率还是蛮低的。为了能更好的进入状态,打算先把JSX相关的知识和细节了解一下。在这篇文章中我们主要就是来学习一下JSX的相关知识。希望对于像我这样的初学React(或初次接触JSX)的同学有所帮助。
什么是JSX
JSX是JavaScript中的一种语法扩展。是React组件编写UI逻辑的语言扩展(JSX除了能在React中使用之外还可以用于别的地方)。虽然在不使用JSX的情况之下,React可以完全正常工作,但它是一种理想的组件处理技术,所以React从JSX中获益良多。
首先,你可能认为使用JSX就是将HTML和JavaScript混合在一起,事实并非如此,因为在使用JSX语法时,描述这个UI不是用字符串,使用的是JavaScript。这让我们能做很多事。
将JavaScript和标记(Markup)放在同一位置被认为是一种坏习惯,但事实证明,将视图与功能结合起来可以直接对视图进行推理。
为了了解这意味着什么,假设我们有一个React组件,它只渲染一个<h1>
标签。JSX允许我们以种非常类似HTML的方式声明这个元素:
class HelloWorld extends React.Component {
render() {
return (
<h1 className="title">Hello World</h1>
)
}
}
HelloWorld
组件中的render()
函数看起来返回的是HTML,但实际上这是JSX。JSX在运行时被转换为常规则JavaScript。翻译后的组件看起来是这样的:
class HelloWorld extends React.Component {
render() {
return (
React.createElement(
'h1',
{className: 'title'},
'Hello World'
)
)
}
}
虽然JSX看起来像HTML,但实际上它只是一种编写React.createElement()
声明的更简洁的方法。当组件渲染时,它输出一个React元素树或该组件输出的HTML元素的虚拟DOM。然后,React将根据这个React元素表示确定对实际DOM进行哪些更改。HelloWorld
组件渲染出来的React的HTML看起来像下面这样:
<h1 class='title'>Hello World</h1>
为什么使用JSX
React认为渲染逻辑本质上与其他UI逻辑内在耦合,比如,在UI中需要绑定处理事件、在某些时刻状态发生变化时需要通知到UI,以及需要在UI中展示准备好的数据。
React并没有采用将标记与逻辑进行分离到不同文件这种人为地分离方式,而是通过将二者共同存放在称之为组件的松散耦合单元之中,来实现“关注点分离”。React不强制要求使用JSX,但大多数人发现,在JavaScript代码中将JSX和UI放在一起时,会在视觉上有辅助作用。它还可以使React显示更多有用的错误和警告消息。
JSX原理
在继续往下阅读之前,先稍微的了解一些有关于JSX原理相关的内容。即JSX是经过怎么样的转化变成页面的元素的。
比如说下面这个最简单的DOM元素为例,怎么使用JavaScript的对象来表现一个DOM元素的结果:
<h1 class="title">Hello World!</h1>
每个DOM元素的结构都可以用JavaScript的对象来表示。你会发现,DOM元素包含的信息其实只有三个:标签名(HTML元素)、属性(HTML元素属性)和子元素(HTML元素或文本节点)。那么上面的这个HTML标签对应的所有信息可以用下面这个对象来描述:
{
tag: 'div',
attrs: {className: 'title'},
children: 'Hello World!'
}
你会发现,HTML的信息和JavaScript所包含的结构和信息其实是一样的,我们可以用JavaScript对象来描述所有能用HTML表示的UI信息。只不过写起来有点麻烦,结构看起来不太清晰。
在React中会把类似HTML的JSX结构转换成JavaScript的对象结构。比如:
<h1 class="title">Hello World!</h1>
JSX转换成JavaScript就会像下面这样:
React.createElement(
"h1",
{
class: "title"
},
"Hello World!"
);
React.createElement()
会构建一个JavaScript对象来描述HTML结构的信息,包括标签名、属性和子元素等。上面是一个较为简单的示例,对于复杂的示例,我们可以借助在线的工具来帮助我们,比如Babel:
所谓的JSX其实就是JavaScript对象。
有了之个表示HTML结构和信息的对象以后,就可以去构造真正的DOM元素,然后使用ReactDOM.render()
函数把构造好的DOM元素塞到页面中:
ReactDOM.render(
<HelloWorld />,
document.getElementById('root')
)
ReactDOM.render()
函数就是把组件渲染并且构造DOM树,然后插入到页面上某个特定的元素上div#root
。
简单地总结一下,JSX经过Babel编译和React构造器转换成了JavaScript对象,然后通过ReactDOM.render()
函数转换成DOM元素,再插入到页面中渲染出来:
接下来简单看看JSX的具体使用。
JSX的使用
在JSX中可以像下面这样定义一个包含字符串的<h1>
标签:
const element = <h1> Hello World!~</h1>
看起来有点像是JavaScript和HTML的结合特,但实际上它就是JavaScript。在JSX中是用来定义组件及其在标记中的位置的语法糖。事实element
是一个Object
:
JSX中嵌入表达式
在下面的示例中,声明了一个名为eleId
的变量,然后在JSX中使用它,并且放置在{}
中,比如:
const eleId = 'title'
const element = <h1 id={eleId}>Hello World!</h1>
在JSX语法中,可以在大括号内放置任何有效的JavaScript表达式,比如:
const Hello = (user) => {
return `Hello ${user}`;
}
const element = <h1>{ Hello('W3cplus.com') }</h1>
在属性中嵌入JavaScript表达式时,不要在大括号外面加上引号。应该仅使用引用(字符串)或大括号(表达式)中的一个,对于同一个属性不能同时使用这两种符号。
JSX中的特定属性
在HTML中标签中有时候会用到带有-
中折号的属性,比如aira-hidden
,也会有多个词组合在一起的属性,比如tabindex
。类似这些属性在JSX中需要使用驼峰写法,比如airaHidden
或tabIndex
。
const eleId='title'
const element = <h1 id={eleId} tabIndex="0">Hello World!</h1>
需要特别注意的是,在JSX中要是会用到class
和for
属性时,需要将class
换成 className
,for
换成 htmlFor
。那是因为class
和for
是JavaScript中的关键字。
const element = (
<div className="control">
<label htmlFor="user">Name:</label>
<input id="user" type="text" placholder="Enter your name" />
</div>
)
在JSX中有些写法和HTML类似,比如一个标签里没有内容,可以使用/>
来闭合标签,比如上面的<input>
元素:
<input id="user" type="text" placholder="Enter your name" />
如果在ReactDOM.render()
包含多个子元素时(JSX标签里包含多个子元素),需要用一个标签元素括起来,比如上面示例中的<div className="control">
。另外将其放置在一个括号()
中。这是因为render()
函数只能返回一个节点,所以如果你想返回两个兄弟节点,就需要添加一个父节点,如上面示例所示。
JSX是一个对象
浏览器不能直接执行包含JSX代码的JavaScript文件。它们必须首先转换成普通的JavaScript。需要一个叫做转置的过程。当然,在React中JSX是可选的,因为对于每个JSX代码都有对应的纯JavaScript代码替代,这就是JSX的换位符。
正如文章开头所提到的,Babel会把JSX转译成一个名为React.createElement()
函数调用。比如下面的两段代码,起到的作用是同等的:
// JSX代码
ReactDOM.render(
<div id="box">
<h1>title</h1>
<p>paragraph</p>
</div>,
document.getElementById('root')
)
// JavaScript
ReactDOM.render(
React.createElement(
"div",
{id: "box"},
React.createElement(
"h1",
null,
"title"
),
React.createElement(
"p",
null,
"paragraph"
)
),
document.getElementById('root')
);
JSX和JavaScript两段代码同样可以借助在线的Babel工具查看。
上面的示例也再次验证了,虽然JSX和JavaScript所起的效果是等效的,但相比而言,JavaScript要比JSX复杂的多。另外React.createElement()
会预先执行一些检查,以帮助你编写无错代码,但实际上它创建了一个这样的对象:
// 简化后的结构
React.createElement(
"h1",
null,
"title"
)
实际上,JSX仅仅只是React.createElement(component, props, ...children)
函数的语法糖。如下JSX代码:
// JSX代码
<MyButton color="blue" shadowSize={2}>
Click Me
</MyButton>
编译成JavaScript代码如下:
// JavaScript代码
React.createElement(
MyButton,
{
color: "blue",
shadowSize: 2
},
"Click Me"
);
JSX中的JS
JSX接受任何混合的JavaScript。当你需要添加一些JavaScript时,只需要将它放到大括号{}
中(前面也有简单的提到过)。例如,下面的示例就是向你展示了在JSX中怎么引用其他地方声明的常量:
const n
如需转载,烦请注明出处:https://www.w3cplus.com/react/in-depth-understanding-of-jsx.html
如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!