总
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> ) }