React Day 2 - JSX in Depth

React 可以用 HTML tags(strings) 或是 React components(classes) 來產生出 HTML tag, 你只需在 JSX 中用小寫的 tag name 來定義 element:

1
2
3
4
5
6
7
8
// HTML tags
var myDivElement = <div className="foo" />
React.render(myDivElement, document.body);

// React component
var MyComponent = React.createClass({/*...*/});
var myElement = <MyComponent someProperty={true} />;
React.render(myElement, document.body);

React 的 JSX 用大寫和小寫命名習慣來區分 componet classes 和 HTML tags


Note:

由於 JSX 其實還是 javascript 語言, 所以有些 HTML 的關鍵字像是 class, for … 等不能直接使用, 你可以用 className, htmlFor … 來轉換

The Transform

1
2
3
4
5
6
7
var Nav;

// JSX
var app = <Nav color="blue" />;

// JS output
var app = React.createElement(Nav, {color: "blue"});

為了讓 JSX 能使用 <Nav />, 我們在區域變數中必須要有一個 Nav 的變數存在.

JSX 也能允許用 XML 的語法定義子元素

1
2
3
4
5
6
7
8
9
10
11
var Nav, Profile;

// JSX
var app = <Nav color="blue"><Profile>click</Profile></Nav>

// JS output
var app = React.createElement(
Nav,
{color: "blue"},
React.createElement(Profile, null, "click")
);


JavaScript Expressions


Attribute Expressions

你可以用 {} 將一個 javascript expression 當作 attrubute value 傳遞進來

1
2
3
4
5
6
7
8
// JSX
var persion = <Persion name={window.isLoggedIn ? window.name : ''} />;

// JS output
var persion = React.createElement(
Persion,
{name: window.isLoggedIn ? window.name : ''}
);
Child Expressions

同樣地, javascript expressions 也可以用在表達子元素的時候:

1
2
3
4
5
6
7
8
9
// JSX
var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;

// JS output
var content = React.createElement(
Container,
null,
window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
);


JSX Spread Attributes

一個明顯地錯誤使用就是在建立 element 之後又修改了 properties:

1
2
3
var component = <Component />;
component.props.foo = x; // bad
component.props.bar = y; // also bad

在新版的 jSX 你可以用 Spread Attributes 的語法將現有的 props 帶入到另一個 component:

1
2
3
4
var props = {};
props.foo = x;
props.bar = y;
var component <Component {...props} />;

你可以多次組合其它的 attributes: (後者會覆蓋前者)

1
2
3
var perops = {foo: 'default'};
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'
1
2
3
4
var oldObj = { foo: 'hello', bar: 'world' };
var newObj = { ...oldObj, foo: 'hi' };
console.log(newObj.foo); // 'hi';
console.log(newObj.bar); // 'world';

合併兩個物件你可以這麼作:

1
var ab = { ...a, ...b };

若你使用 react-tools Precompilier, 你需要加上 --harmony 參數來開啟這個語法的解析

Custom HTML Attributes

如果你要帶入的 properties 並不是標準的 HTML 規格, React 並不會把它 render 出來. 如果你想使用自訂的 attribute, 你應該在前綴加上 data-:

1
<div data-custom-attribute="foo" />

Web Accessibility 的 attributes 前綴為 aria- 將會被 render

1
<div aria-hidden={true} />