2.JSX

為什么要引入 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 代碼才能使用哺窄。

JSX 是可選的

因為 JSX 最終是輸出成 JS 代碼來表達的,所以我們可以直接用 React 提供的這些 DOM 構建方法來寫模板账锹,比如一個 JSX 寫的一個鏈接:

<a >Hello!</a>

用 JS 代碼來寫就成這樣了:

React.createElement('a', {href: 'http://facebook.github.io/react/'}, 'Hello!')

你可以通過 React.createElement 來構造組件的 DOM 樹萌业。第一個參數(shù)是標簽名,第二個參數(shù)是屬性對象牌废,第三個參數(shù)是子元素。

一個包含子元素的例子:

var child = React.createElement('li', null, 'Text Content');
var root = React.createElement('ul', { className: 'my-list' }, child);
React.render(root, document.body);

對于常見的 HTML 標簽啤握,React 已經(jīng)內(nèi)置了工廠方法:

var root = React.DOM.ul({ className: 'my-list' },
             React.DOM.li(null, 'Text Content')
           );

所以 JSX 和 JS 之間的轉換也很簡單直觀鸟缕,用 JSX 的好處就是它基本上就是HTML(后面會講到有一些小差異),對于構造 DOM 來說我們更熟悉排抬,更具可讀性懂从。

關于 JSX 映射成 JS 對象,也就是 Virtual DOM 的內(nèi)部描述蹲蒲,參見Virtual DOMTerminology番甩,如果你不想使用JSX,直接使用 JS 就是用這里面提到的接口方法届搁。

使用 JSX

利用 JSX 編寫 DOM 結構缘薛,可以用原生的 HTML 標簽,也可以直接像普通標簽一樣引用 React組件卡睦。這兩者約定通過大小寫來區(qū)分宴胧,小寫的字符串是 HTML 標簽,大寫開頭的變量是 React 組件表锻。

使用 HTML 標簽:

import React from 'react';
import { render } from 'react-dom';

var myDivElement = <div className="foo" />;
render(myDivElement, document.getElementById('mountNode'));

HTML 里的 class 在 JSX 里要寫成 className恕齐,因為 class 在 JS 里是保留關鍵字。同理某些屬性比如 for 要寫成 htmlFor瞬逊。

使用組件:

import React from 'react';
import { render } from 'react-dom';
import MyComponent from './MyComponet';

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

使用 JavaScript 表達式

屬性值使用表達式显歧,只要用 {} 替換 "":

// Input (JSX):
var person = <Person name={window.isLoggedIn ? window.name : ''} />;
// Output (JS):
var person = React.createElement(
  Person,
  {name: window.isLoggedIn ? window.name : ''}
);

子組件也可以作為表達式使用:

// Input (JSX):
var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
// Output (JS):
var content = React.createElement(
  Container,
  null,
  window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
);

注釋

在 JSX 里使用注釋也很簡單,就是沿用 JavaScript确镊,唯一要注意的是在一個組件的子元素位置使用注釋要用 {} 包起來士骤。

var content = (
  <Nav>
      {/* child comment, put {} around */}
      <Person
        /* multi
           line
           comment */
        name={window.isLoggedIn ? window.name : ''} // end of line comment
      />
  </Nav>
);

HTML 轉義

React 會將所有要顯示到 DOM 的字符串轉義,防止 XSS蕾域。所以如果 JSX 中含有轉義后的實體字符比如 ? (?) 最后顯示到 DOM 中不會正確顯示敦间,因為 React 自動把 ? 中的特殊字符轉義了。有幾種解決辦法:

  • 直接使用 UTF-8 字符 ?
  • 使用對應字符的 Unicode編碼,查詢編碼
  • 使用數(shù)組組裝 <div>{['cc ', <span>?</span>, ' 2015']}</div>
  • 直接插入原始的 HTML
<div dangerouslySetInnerHTML={{__html: 'cc &copy; 2015'}} />

自定義 HTML 屬性

如果在 JSX 中使用的屬性不存在于 HTML的規(guī)范中廓块,這個屬性會被忽略厢绝。如果要使用自定義屬性,可以用data-前綴带猴。

可訪問性屬性的前綴aria-也是支持的昔汉。

支持的標簽和屬性

如果你要使用的某些標簽或屬性不在這些支持列表里面就可能被 React 忽略,必須要使用的話可以提 issue拴清,或者用前面提到的 dangerouslySetInnerHTML靶病。

屬性擴散

有時候你需要給組件設置多個屬性,你不想一個個寫下這些屬性口予,或者有時候你甚至不知道這些屬性的名稱娄周,這時候 spreadattributes 的功能就很有用了。

比如:

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

props 對象的屬性會被設置成 Component 的屬性沪停。

屬性也可以被覆蓋:

var 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 SpreadProperties.

JSX 與 HTML 的差異

除了前面提到的 class 要寫成 className ,比較典型的還有:

  • style 屬性接受由 CSS 屬性構成的 JS 對象
  • onChange 事件表現(xiàn)更接近我們的直覺(不需要 onBlur 去觸發(fā))
  • 表單的表現(xiàn)差異比較大木张,要單獨再講

更多異同众辨,可以參見 DOMDifferences

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市舷礼,隨后出現(xiàn)的幾起案子鹃彻,更是在濱河造成了極大的恐慌,老刑警劉巖妻献,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛛株,死亡現(xiàn)場離奇詭異,居然都是意外死亡育拨,警方通過查閱死者的電腦和手機泳挥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來至朗,“玉大人屉符,你說我怎么就攤上這事∏乱” “怎么了矗钟?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長嫌变。 經(jīng)常有香客問我吨艇,道長,這世上最難降的妖魔是什么腾啥? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任东涡,我火速辦了婚禮冯吓,結果婚禮上,老公的妹妹穿的比我還像新娘疮跑。我一直安慰自己组贺,他們只是感情好,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布祖娘。 她就那樣靜靜地躺著失尖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪渐苏。 梳的紋絲不亂的頭發(fā)上掀潮,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機與錄音琼富,去河邊找鬼仪吧。 笑死,一個胖子當著我的面吹牛鞠眉,可吹牛的內(nèi)容都是我干的薯鼠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼凡蚜,長吁一口氣:“原來是場噩夢啊……” “哼人断!你這毒婦竟也來了吭从?” 一聲冷哼從身側響起朝蜘,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涩金,沒想到半個月后谱醇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡步做,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年副渴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片全度。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡煮剧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出将鸵,到底是詐尸還是另有隱情勉盅,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布顶掉,位于F島的核電站草娜,受9級特大地震影響,放射性物質發(fā)生泄漏痒筒。R本人自食惡果不足惜宰闰,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一茬贵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧移袍,春花似錦解藻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至戳粒,卻和暖如春路狮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蔚约。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工奄妨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人苹祟。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓砸抛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親树枫。 傳聞我的和親對象是個殘疾皇子直焙,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容

  • JSX 知識準備 JSX 并不是一門全新的語言,僅僅是一個語法糖砂轻,允許開發(fā)者在javascript中編寫XML語言...
    艾倫先生閱讀 4,505評論 4 20
  • 以下內(nèi)容是我在學習和研究React時奔誓,對React的特性、重點和注意事項的提取搔涝、精練和總結厨喂,可以做為React特性...
    科研者閱讀 8,233評論 2 21
  • 按照慣例,先給ReactJS背書 React是一個Facebook開發(fā)的UI庫庄呈,于2013年5月開源蜕煌,并迅速的從最...
    艾倫先生閱讀 3,236評論 1 12
  • JSX是React的核心組成部分,它使用XML標記的方式去直接聲明界面诬留,界面組件之間可以互相嵌套斜纪。可以理解為在JS...
    可樂愛上咖啡閱讀 71,952評論 1 64
  • 自己最近的項目是基于react的文兑,于是讀了一遍react的文檔盒刚,做了一些記錄(除了REFERENCE部分還沒開始讀...
    潘逸飛閱讀 3,390評論 1 10