总
JSX:本质上来说,JSX只是React.createElement(component, prop, ...children) 方法的语法糖
<myHeader someData={data}>
Header Content
</myHeader>
等价于:
React.createElement(
'myHeader', // Type
{someData: data}, // props
'Header Content' // ...children
)
JSX的语法与原生html标签有一定相似性,不含有子节点的标签可以使用“自闭和”形式
<myHeader someData={data} />
它的...children参数就被设置为null,接下来我们逐个分析JSX语法里的各个元素
(一)JSX Type
Type:JSX语法的第一部分决定了React Element的类型
<MyElement />
大写的Type表明了它是一个React组件的引用,所以你必须保证(1)“MyElement”在作用域中;同时因为JSX会被编译成为React.Component(...)的形式,所以你还必须保证(2)React的library在作用域中
import React from 'react' // React library
import MyElement from '...' // MyElement Component
function doSth() {
return <MyElement />
}
就像这样
其他值得注意的:
1.在JSX TYPE中使用“.”来指明React Component
const MyComponets = {
Header: function Header(props) {
return (<div>This is header</div>)
}
Footer: function Footer(props) {
return (<div>This is footer</div>)
}
}
function doSth() {
return <MyComponents.Header />
}
2.请对自定义组件首字母大写
首字母小写的JSX Type代表着内置组件,如div, p, span,React会将它作为html标签
3.运行时选择Type
你不能使用表达式作为JSX的Type,但是可以将它的结果赋值给一个首字母大写的变量
function doSth(props) {
return <MyComponents[props.Header] /> // Wrong!
}
functin doSth(props) {
const Header = MyComponents[props.Header]; // True!
return <Header />
}
(二)JSX props
JSX 的 props有多种指定的方式:
1.JavaScript Expression
就像:
<MyComponent myProp={1 + 2 / 1} />
注意:if 语句和 for循环并不是Expression,所以不能直接放在props中,但是可以放在JSX外达成相同的效果:
<MyComponent
myShow={if (flag === true) {return true;} else {return false;}} // wrong!
myList={for (item in list) {return doSth(item);}} //wrong!
/>
正确的做法是:
for (item in list) {
const show;
const result;
if (flag === true) {
show = true;
}
result = doSth(result);
return <MyComponent myShow={show} myList={result} />
}
2.字符串字面量
以下两种方式是等价的:
<MyComponent myString={'Hello'} />
<MyComponent myString="Hello" />
在字面量中,你甚至可以使用'<sth'的内容,他并不会引起标签未闭合的错误
3.使用默认值
指定一个prop的时候,如果不指定值,那他默认是 true。但是很不推荐这样做,因为在ES6的规范中,{foo}是{foo: foo}的简写形式,容易引起混淆
4.可扩展属性
可以将一个对象作为props传入JSX
function doSth() {
return <MyComponent prop1={prop1value} prop2={prop2value} />
}
function doSth() {
const myProps = {
prop1: prop1value,
prop2: prop2value
}
return <MyComponent {...myProps} />
}
以上两种用法是等价的
更进一步,可以将props解构成特定的props,并将其他的props放入可扩展属性中,如:
function Header = props => {
const {title, ...other} = props;
return <div {...other}>{ title }</div>;
}
总结起来,这种方式虽然使用方便,但是有可能吧不重要的属性也传入;并且可能传入不合法的属性;所以,请谨慎使用
(三)JSX Children
子元素是一个特殊的prop-props.children,位于JSX标签之中,它可以通过多种方法传入:
注意:这些方法都可以混合使用
1.字符串字面量:
<MyComponent>Hello</MyComponent>
JSX会自动去除多余的空行和空格
2.JSX Children
<MyComponent>
<ChildComponent />
<ChildComponent />
<ChildComponent />
</MyComponent>
可以将其他JSX元素作为子元素
ReactComponent可以返回一个元素的数组
render() {
return [
<li>Child1</li>
<li>Child2</li>
<li>Child3</li>
]
}
3.JavaScript Expression
惯用法:渲染一个JSX表达式的列表
render() {
return (
<ul>{items.map(item => <li color={ item.color }>{ item.title }</li>)}</ul>
)
}
4.函数
可以传入自定义组件的子元素可以是任意的,就像其他prop
// Calls the children callback numTimes to produce a repeated component
function Repeat(props) {
let items = [];
for (let i = 0; i < props.numTimes; i++) {
items.push(props.children(i)); // 这里传入的i作为子元素(函数)的index参数
}
return <div>{items}</div>;
}
function ListOfTenThings() {
return (
<Repeat numTimes={10}>
{(index) => <div key={index}>This is item {index} in the list</div>}
</Repeat>
);
}
很不常用,但是JSX可以做到!
5.Boolean, Null, undefined 会被忽视
它们不会被渲染
Tips:用于条件渲染
render() {
return(
<div>
{isTrue && <MyComponent />}
</div>
)
}
请注意,0之类的“类错误”值并不会被忽视,请用 expressionCanBiggerThanZero > 0的表达式来替换0值,如:
render() {
return(
<div>
{ message.length > 0 && <MyComponents />} // 直接使用message.length不会产生预期结果
</div>
)
}
另外,如果你想让false、true、null、undefined出现在输出中,请转换为字符串
render() {
return(
<div>
{ String(isTrue) }
</div>
)
}