JSX
是 JavaScript
的扩展语法,这种 <MyButton></MyButton>
标签的写法就是 JSX。JSX 编写的组件通过预处理器 babel 解析后,再交给 React 库渲染到指定父容器下,形成最终html页面。
<MyButton color="blue" shadowSize={2}>
Click Me
</MyButton>
上面 jsx 写的组件,被 babel 解析下如下代码:
React.createElement(
MyButton,
{ color: 'blue', shadowSize: 2 },
'Click Me'
)
// jsx声明变量
const element = <h1>Hello, world!</h1>;
// jsx中设置属性
const element = <div tabIndex="0"></div>;
const element = <img src={user.avatarUrl}></img>;
const element = <img src={user.avatarUrl} />;
// jsx中可以包含多个子元素
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);
// jsx作为表达式,用在return返回
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}
{}
{}
使得 jsx
可以直接使用 js
语法表达式。
// JSX 中调用 js 函数:
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'Harper',
lastName: 'Perez'
};
const element = (
<h1>
Hello, {formatName(user)}!
</h1>
);
// 渲染element元素并加载到父容器root下
ReactDOM.render(
element,
document.getElementById('root')
);
# JSX 嵌入 复杂表达式
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
)}
</ul>
);
}
.
点语法,表示模块中的某一个组件。如下,使用MyComponents模块中的DatePicker组件,点语法非常方便。
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" />;
}
...
用展开运算符 ...
来传递整个 props 对象。以下两个组件是等价的:
function App1() {
return <Greeting firstName="Ben" lastName="Hector" />;
}
function App2() {
const props = { firstName: 'Ben', lastName: 'Hector' };
return <Greeting {...props} />;
}
// 用法2:导出需要修改属性kind,其他属性用...来表示
const Button = props => {
const { kind, ...other } = props;
const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton";
return <button className={className} {...other} />;
};
const App = () => {
return (
<div>
<Button kind="primary" onClick={() => console.log("clicked!")}>
Hello World!
</Button>
</div>
);
};
JSX 写的组件名字,必须以大写字母开始。
import React from 'react';
// 正确!组件需要以大写字母开头:
function Hello(props) {
// 正确! 这种 <div> 的使用是合法的,因为 div 是一个有效的 HTML 标签:
return <div>Hello {props.toWhat}</div>;
}
function HelloWorld() {
// 正确!React 知道 <Hello /> 是一个组件,因为它是大写字母开头的:
return <Hello toWhat="World" />;
}
用大写变量SpecificStory 作为元素名称,运行期间根据 props 属性值,决定加载什么组件,非常方便。
import React from 'react';
import { PhotoStory, VideoStory } from './stories';
const components = {
photo: PhotoStory,
video: VideoStory
};
function Story(props) {
// 正确!JSX 类型可以是大写字母开头的变量。
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}
True
// 下面这两句是等价的
<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />
props.children 可以表示任意类型的子元素:
// props.children 是一个简单的未转义字符串 "Hello world!"
function Welcome(props) {
return <p>{props.children}</p>;
}
<Welcome>Hello world!</Welcome>
// props.children 表示回调函数: {(index) => <div key={index}>This is item {index} in the list</div>}
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>
);
}
// 1、只有showHeader 为true时, Header才会被加载渲染
<div>
{showHeader && <Header />}
<Content />
</div>
// 2、即使 props.messages.length 为0,MessageList也会被加载
<div>
{props.messages.length &&
<MessageList messages={props.messages} />
}
</div>
// 3、上面代码修改如下,可符合预期
<div>
{props.messages.length > 0 &&
<MessageList messages={props.messages} />
}
</div>
// 4、如下子元素是不会被渲染
<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>
// 5、只能把他们转为字符串显示
<div>
My JavaScript variable is {String(myVariable)}.
</div>
class Hello extends React.Component {
render() {
return <div>Hello {this.props.toWhat}</div>;
}
}
ReactDOM.render(
<Hello toWhat="World" />,
document.getElementById('root')
);
class Hello extends React.Component {
render() {
return React.createElement('div', null, `Hello ${this.props.toWhat}`);
}
}
ReactDOM.render(
React.createElement(Hello, { toWhat: 'World' }, null),
document.getElementById('root')
);