一闲延、什么是JSX
使用JSX聲明一個變量(React 當中的元素):
const element = <h1>Hello, world!</h1>;
JSX是一種 JavaScript 的語法擴展渣玲。 我們推薦在 React 中使用 JSX 來描述用戶界面哄尔。JSX 乍看起來可能比較像是模版語言街立,但事實上它完全是在 JavaScript 內(nèi)部實現(xiàn)的酸役。
二癣漆、為什么要使用JSX
傳統(tǒng)的 MVC 是將模板放在其他地方,比如 <script> 標簽或者模板文件渠啤,再在 JS 中通過某種手段引用模板狐肢。按照這種思路,想想多少次我們面對四處分散的模板片段不知所措沥曹?糾結模板引擎份名,糾結模板存放位置碟联,糾結如何引用模板……下面是一段 React 官方的看法:
We strongly believe that components are the right way to separate concerns rather than "templates" and "display logic." We think that markup and the code that generates it are intimately tied together. Additionally, display logic is often very complex and using template languages to express it becomes cumbersome.
簡單來說,React 認為組件才是王道僵腺,而組件是和模板緊密關聯(lián)的鲤孵, JSX 這種語法,就是為了把HTML
模板直接嵌入到JS
代碼里面辰如,這樣就做到了模板和組件關聯(lián)普监,但是 JS 不支持這種包含 HTML 的語法,所以需要通過工具將 JSX 編譯輸出成 JS 代碼才能使用琉兜。
npm install babel-loader --save-dev
三凯正、載入方式
JSX 目前有兩種方法載入。
1. 內(nèi)聯(lián)方式載入
<script type="text/babel">
ReactDOM.render(
<h1>hello hangge.com</h1>,
document.getElementById('example')
);
</script>
2. 外聯(lián)方式載入
即將 JSX 代碼單獨放在一個.jsx 文件中豌蟋。
ReactDOM.render(
<h1>hello hangge.com</h1>,
document.getElementById('example')
);
然后在頁面上通過下面的方式引入這個 .jsx 文件廊散。
<script type="text/babel" src="hello.jsx"></script>
四、在 JSX 中使用表達式
可以任意地在 JSX 當中使用 JavaScript 表達式梧疲,在 JSX 當中的表達式要包含在大括號里(個人理解就是寫在JS里的HTML里的JS需要{}大括號)允睹。
// 定義一個函數(shù),返回傳入的名字的拼寫后的結果
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
// 定義一個數(shù)據(jù)類型為對象的常量
const user = {
firstName: 'Harper',
lastName: 'Perez'
};
// 使用JSX語法來定義一個html標簽(所以element為小寫開頭)
const element = (
<h1>
Hello, {formatName(user)}!
</h1>
);
// 渲染這個html標簽
ReactDOM.render(
element,
document.getElementById('root')
);
注意:
- 我們書寫 JSX 的時候一般都會帶上換行和縮進往声,這樣可以增強代碼的可讀性擂找。
- 與此同時,我們同樣推薦在 JSX 代碼的外面擴上一個小括號浩销,這樣可以防止 分號自動插入 的 bug贯涎。
五、JSX 本身其實也是一種表達式
在編譯之后呢慢洋,JSX 其實會被轉化為普通的 JavaScript 對象塘雳。
這也就意味著,你其實可以在 if 或者 for 語句里使用 JSX普筹,將它賦值給變量败明,當作參數(shù)傳入,作為返回值都可以:
// 定義一個函數(shù)太防,如果有傳參數(shù)進來就把名字拼寫好返回妻顶,否則就返回陌生人
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}
六、JSX 屬性
- 你可以使用引號來定義以字符串為值的屬性:
const element = <div tabIndex="0"></div>;
- 也可以使用大括號來定義以 JavaScript 表達式為值的屬性:
const element = <img src={user.avatarUrl}></img>;
切記使用了大括號包裹的 JavaScript 表達式時就不要再到外面套引號了蜒车。JSX 會將引號當中的內(nèi)容識別為字符串而不是表達式讳嘱。(不要src="{user.avatarUrl}",會以為src為{user.avatarUrl})
七酿愧、JSX 嵌套
如果 JSX 標簽是閉合式的沥潭,那么你需要在結尾處用/>
, 就好像 XML/HTML 一樣:
const element = <img src={user.avatarUrl} />;
JSX 標簽同樣可以相互嵌套:(當換行和縮進的時候,使用括號包住它們)
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);
警告:
因為 JSX 的特性更接近 JavaScript 而不是 HTML , 所以 React DOM 使用camelCase
小駝峰命名 來定義屬性的名稱嬉挡,而不是使用 HTML 的屬性名稱钝鸽。(概括就是: JSX使用小駝峰命名定義屬性的名稱)
例如汇恤,class
變成了className
,而tabindex
則對應著tabIndex
拔恰。
八因谎、JSX 防注入攻擊
你可以放心地在 JSX 當中使用用戶輸入:
const title = response.potentiallyMaliciousInput;
// 直接使用是安全的:
const element = <h1>{title}</h1>;
React DOM 在渲染之前默認會 過濾 所有傳入的值。它可以確保你的應用不會被注入攻擊仁连。所有的內(nèi)容在渲染之前都被轉換成了字符串蓝角。這樣可以有效地防止 XSS(跨站腳本) 攻擊。
九饭冬、HTML 轉義
React 會將所有要顯示到 DOM 的字符串轉義,防止 XSS揪阶。所以如果 JSX 中含有轉義后的實體字符比如 ©
(?) 最后顯示到 DOM 中不會正確顯示昌抠,因為 React 自動把 ©
中的特殊字符轉義了。有幾種解決辦法:
- 直接使用 UTF-8 字符 ?
- 使用對應字符的 Unicode 編碼鲁僚,查詢編碼
- 使用數(shù)組組裝
<div>{['cc ', <span>©</span>, ' 2015']}</div>
- 直接插入原始的 HTML
<div dangerouslySetInnerHTML={{__html: 'cc © 2015'}} />
十炊苫、JSX 代表 Objects
Babel 轉譯器會把 JSX 轉換成一個名為React.createElement()
的方法調(diào)用。
下面兩種代碼的作用是完全相同的:
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
React.createElement() 這個方法首先會進行一些避免bug的檢查冰沙,之后會返回一個類似下面例子的對象:
// 注意: 以下示例是簡化過的(不代表在 React 源碼中是這樣)
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world'
}
};
這樣的對象被稱為 “React 元素”
侨艾。它代表所有你在屏幕上看到的東西。
React 通過讀取這些對象來構建 DOM 并保持數(shù)據(jù)內(nèi)容一致拓挥。
十一唠梨、注釋
在 JSX 里使用注釋也很簡單,就是沿用 JavaScript侥啤,唯一要注意的是在一個組件的子元素位置使用注釋要用 {} 包起來当叭。
var content = (
<Nav>
{/* child comment, put {} around */}
<Person
/* multi
line
comment */
name={window.isLoggedIn ? window.name : ''} // end of line comment
/>
</Nav>
);
十二、自定義 HTML 屬性
如果在 JSX 中使用的屬性不存在于 HTML 的規(guī)范中盖灸,這個屬性會被忽略蚁鳖。如果要使用自定義屬性,可以用 data-
前綴赁炎。
可訪問性屬性的前綴 aria-
也是支持的醉箕。
支持的標簽和屬性
如果你要使用的某些標簽或?qū)傩圆辉谶@些支持列表里面就可能被 React 忽略,必須要使用的話可以提 issue徙垫,或者用前面提到的 dangerouslySetInnerHTML
讥裤。
十三、屬性擴散
有時候你需要給組件設置多個屬性松邪,你不想一個個寫下這些屬性坞琴,或者有時候你甚至不知道這些屬性的名稱,這時候 spread attributes 的功能就很有用了逗抑。
比如:
var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
props 對象的屬性會被設置成 Component 的屬性剧辐。
屬性也可以被覆蓋:
ar props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'
寫在后面的屬性值會覆蓋前面的屬性寒亥。
關于
...
操作符
The...
operator (or spread operator) is already supported for arrays in ES6. There is also an ES7 proposal for Object Rest and Spread Properties.