本质上讲,JSX 只是 React.createElement(component, props, ...children)
的语法糖(JSX 在线Babel编译器)。所以,在用到 JSX 时,即便并无用到React
,做用域中也必须包含 React 库:import React from 'react'
。例如:node
写函数组件时,react
function Welcome(props) { return <h1>Hello, {props.name}</h1>; }
配置文件 Object 中包含 JSX:数组
{ ... render: (data) => <div>{data}</div> ... }
小写字母开头: 内置组件,HTML 元素,例如 <div>
,<span>
,会编译成 React.createElement('div')
。
大写字母开头:自定义组件或 JS 文件中导入的组件,例如 <Foo />
,<MyComponents.DatePicker />
,会编译成 React.createElement(Foo)
。
例外:在 JSX 中使用点语法(Dot Notation)表示一个 React 组件 <obj.component />
会编译成 React.createElement(obj.component)
。
解释:JSX 语法依赖babel进行解析。在 @babel/plugin-transform-react-jsx 中,babel
const visitor = helper({ pre(state) { const tagName = state.tagName; const args = state.args; if (t.react.isCompatTag(tagName)) { args.push(t.stringLiteral(tagName)); } else { args.push(state.tagExpr); } }, post(state, pass) { state.callee = pass.get("jsxIdentifier")(); }, throwIfNamespace: THROW_IF_NAMESPACE, });
function isCompatTag(tagName) { return !!tagName && /^[a-z]/.test(tagName); }
即小写字母开头的 tagName 直接转为 string 字符串;ide
// returns a closure that returns an identifier or memberExpression node // based on the given id const createIdentifierParser = (id: string) => () => { return id .split(".") .map(name => t.identifier(name)) .reduce((object, property) => t.memberExpression(object, property)); };
即在 JSX 中使用点语法(Dot Notation)时,无论是大写仍是小写,最终都会解析成对象和属性,而不是字符串,也因此虽然 C[p] 和 C.p 同样,可是 JSX 中 <c.p /> 能够解析而 <c[p] /> 不行。函数
import React from 'react'; import { PhotoStory, VideoStory } from './stories'; const components = { photo: PhotoStory, video: VideoStory }; function Story(props) { // 错误!JSX 类型不能是表达式 return <components[props.storyType] story={props.story} />; // 正确!JSX 类型能够是一个以大写字母开头的变量. const SpecificStory = components[props.storyType]; return <SpecificStory story={props.story} />; }
JSX 是表达式,编译后就变成常规的 Javascript 对象,因此能够post
const button = <button>{name}</button>
当作参数接收this
getFieldDecorator('price', { initialValue: { number: 0, currency: 'rmb' }, rules: [{ validator: this.checkPrice }], })(<PriceInput />)
render: () => <Foo />
JSX props 能够用 Javascript 表达式或字符串字面量。props.children(标签中的内容) 是个特殊的 props。
在 JavaScript 中,if 语句和 for 循环不是表达式,所以不能在 JSX 中直接使用。spa
falsy 是在 Boolean 上下文中已认定可转换为‘假’的值。code
if (false) if (null) if (undefined) if (0) if (NaN) if ('') if ("") if (document.all)
false,null,undefined,和 true 是有效的children,可是不会被渲染;
falsy 值例如 0,则会被渲染,例如:
// props.messages 是空数组时,props.messages.length 为 0 会被渲染出来。 <div> {props.messages.length && <MessageList messages={props.messages} /> } </div>
应该改为:
<div> {props.messages.length > 0 && <MessageList messages={props.messages} /> } </div>