JSX构建元素
之前我们使用 React.createElement
来构建ReactElement
:
var boldElement = React.createElement('b', null, 'Text (as a string)')
当我们构建小组件的时候,这种方法用起来还行,但是如果我们要构建许多有相互嵌套的组件的时候,这种方法就显得很麻烦了。
我们可以想着一种方式:我们编写HTML来告诉浏览器页面应该是什么样的;浏览器解析这种HTML变成可以变成DOM元素的HTML。
HTML对于描述元素的层级关系是非常好的。所以,React用类似于HTML的方式来表达React组件。
这就是JSX背后的思想。
我们可以将刚刚的React.createElement
方式构建的元素用JSX替代:
var boldElement = <b>Text (as a string)</b>
JSX是JavaScript的一种语法拓展(JavaScript Syntax Extension)
,这是React提供的看起来像HTML/XML的一种语法。我们用这个方法编写组件就好像使用HTML那样,而不是直接使用JavaScript的方式。
尽管JSX提供的语法很像HTML,但是JSX可以让我们构建自己的标签(例如将其他功能性的组件封装起来成为一个标签)。
React组件和HTML标签的区别之一就是它的命名方式。HTML标签的首字母是小写的,而React组件的首字母必须大写。例如:
// html标签
const htmlElement = (<div>hello world</div>)
// React组件
const Message = props => (<div>{props.text}</div>)
我们通常会使用圆括号()
将JSX包裹起来。尽管这不是必须的,但是这种方式有助于我们区分JavaScript和JSX。
但是浏览器并不能识别出JSX,那么JSX又怎么能渲染到浏览器上?
这是因为通过使用预处理的构建工具将JSX编译成JavaScript,这样浏览器就能识别了。
除了能写起来像HTML,JSX还要其他的优势:我们可以在JSX中混写JavaScript。这样就能让我们在试图中添加逻辑。
我们已经见过一些基本的JSX的使用方法了,接下来我们将会讨论一下JSX的如下方面:
- 属性表达式
- 条件组件
- 布尔属性
- 注释
JSX属性表达式
为了在组件属性中使用JavaScript表达式,我们需要使用{}
。在{}
写JavaScript表达式,而不能使用""
。
const warningLevel = 'debug'
const component = (
<Alert
color={warningLevel === 'debug' ? 'gray' : 'red' }
log={true} />
)
这个例子中,我们使用三目表达式来判断color
的颜色。
JSX条件表达式
另一种通常的模式是用布尔的方式检查表达式,然后条件的渲染组件。
例如,如果我们想要构建一个菜单以条件的显示admin
用户,我们可以这样书写:
const renderAdminMenu = () => {
return (
<MenuLink to="/users">User accounts</MenuLink>
)
}
const userLevel = this.props.userLevel
return (
<ul>
<li>Menu</li>
{userLevel === 'admin' && renderAdminMenu() }
</ul>
)
我们同样可以使用三目表达式来条件渲染组件。
`const Menu = (<ul>{loggedInUser ? <UserMenu/> : <LoginLink/>}</ul>)
JSX布尔属性
在HTML中,一些属性默认是设置成true
的。例如一个disabled
的input
标签:
<input name="Name" disabled/>
在React中,我们需要设置这些布尔值。也就是说,我们需要显式的给属性传递true
或者false
。
<input name="Name" disabled={true} />
let formDisabled = true
<input name="Name" disabled={formDisabled} />
JSX注释
在JSX中,我们使用{/* ... */}
的方式书写注释。
let userLevel = 'admin'
{/*
Show the admin menu if the userLevel is 'admin'
*/}
{userLevel === 'admin' && <AdminMenu/>}
JSX的spread语法
有些时候,我们要给组件传递很多props
,但是一个一个的书写这些props
是很麻烦的。JSX有一个简写的语法使得多个props
的传递变得容易。
例如:
const props = {msg: 'Hello', recipient: 'World'}
我们可以一个一个的传递props
,就像这样:
<Component mgs={'Hello'} recipient={'World'} />
但是通过使用JSX的spread语法,我们可以这样来写:
<Component {...props} />
// 两种方式是一样的
<Component mgs={'Hello'} recipient={'World'} />
JSX其他
class
和className
,for
和htmlFor
当我们想要在HTML元素中添加CSS类的时候,我们通常是在标签内使用class
:
<div class="box"></div>
由于JSX本质上是JavaScript,所以我们不能再JSX中使用JavaScript的关键字。所以HTML中的class和for是不能用在JSX中的,因为class和for是JavaScript的关键字。
所以在JSX中,使用className
替代class
,使用htmlFor
替代for
。
<div className="box"></div>
<label htmlFor="email">Email</label>
<input name="email" type="email" id="email" />
JSX小结
JSX并不是魔法。我们始终牢记一点,JSX本质上就是JavaScript,它是React.createElement
的语法糖。JSX是我们构建组件树的一种方便的书写方式。