深入JSX

JSX 其实是 React. createElement(component, props, …children) 函数的语法糖。故使用 jsx 前,需先引用 React 库。

1
2
3
4
5
6
7
8
9
10
11
12
import React from 'react';//先引用react库
<MyButton color="blue" shadowSize={2}>
Click Me
</MyButton>

//上面jsx会编译成如下代码:

React.createElement(
MyButton,
{color: 'blue', shadowSize: 2},
'Click Me'
)

1 JSX 组件标签

  • 大写字母开头的 JSX 标签才会被识别为 React 组件

  • 组件标签可以使用点语法

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';

const MyComponents = {
DatePicker: function DatePicker(props) {
return <div>Imagine a {props.color} datepicker here.</div>;
}
}

function BlueDatePicker() {
return <MyComponents.DatePicker color="blue" />;
}
  • 组件标签不能为表达式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
photo: PhotoStory,
video: VideoStory
};

function Story(props) {
//错误,标签不能为表达式components[props.storyType]
return <components[props.storyType] story={props.story} />;
// 正确!JSX 类型可以是大写字母开头的变量。
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}

2 JSX 中的 Props

JSX 中的 props 可以为 JS 表达式、字符串,props 属性的默认值为 ture,可以将对象使用展开运算符传递给Props。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//使用js表达式
<MyComponent foo={1 + 2 + 3 + 4} />

//下面两个字符串值等价
<MyComponent message="&lt;3" />
<MyComponent message={'<3'} />

//下面两者等价,props 属性默认值为 true
<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />

//将对象使用展开运算符...传递给Props
function App2() {
const props = {firstName: 'Ben', lastName: 'Hector'};
return <Greeting {...props} />;
}

3 JSX 中的子元素

JSX 组件的开始和结束标签之间的内容,会通过 Props.children 传递给组件。

3.1 字符串、表达式、函数

字符串为子元素时,JSX 会移除行首尾的空格及空行,字符串之间的新行会被压缩为一个空格,下面几种书写方式是等效的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<div>Hello World</div>

<div>
Hello World
</div>

<div>
Hello
World
</div>

<div>

Hello World
</div>

//js表达式为子元素
function Item(props) {
return <li>{props.message}</li>;
}

function TodoList() {
const todos = ['finish doc', 'submit pr', 'nag dan to review'];
return (
<ul>
{todos.map((message) => <Item key={message} message={message} />)}
</ul>
);
}

//函数为子元素
function Repeat(props) {
let items = [];
for (let i = 0; i < props.numTimes; i++) {
items.push(props.children(i));
}
return <div>{items}</div>;
}

function ListOfTenThings() {
return (
<Repeat numTimes={10}>
{(index) => <div key={index}>This is item {index} in the list</div>}
</Repeat>
);
}

3.2 组件

1
2
3
4
<MyContainer>
<MyFirstComponent />
<MySecondComponent />
</MyContainer>

3.3 布尔类型、Null 以及 Undefined

布尔类型、Null 以及 Undefined 将会忽略

1
2
3
4
5
6
7
8
9
10
11
12
//以下的 JSX 表达式渲染结果相同:
<div />

<div></div>

<div>{false}</div>

<div>{null}</div>

<div>{undefined}</div>

<div>{true}</div>

值得注意的是有一些 “falsy” 值,如数字 0,仍然会被 React 渲染。例如,以下代码并不会像你预期那样工作,因为当 props.messages 是空数组时,0 仍然会被渲染:

1
2
3
4
5
<div>
{props.messages.length &&
<MessageList messages={props.messages} />
}
</div>

要解决这个问题,确保 && 之前的表达式总是布尔值:

1
2
3
4
5
<div>
{props.messages.length > 0 &&
<MessageList messages={props.messages} />
}
</div>

反之,如果你想渲染 falsetruenullundefined 等值,你需要先将它们转换为字符串

1
2
3
<div>
My JavaScript variable is {String(myVariable)}.
</div>