本質上講,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>