最近幾個月作的一個項目,使用了react技術體系,天然而然的用到了JSX。下面就總結一下本身對JSX的認識。javascript
即JavaScript XML,一種在React組建內部構建標籤的類XML語法。(加強React程序組件的可讀性)php
JSX能夠看做JavaScript的拓展,看起來有點像XML。使用React,能夠進行JSX語法到JavaScript的轉換。css
下面咱們來看一下一個簡單的例子。
考慮一下這個變量的聲明:html
const element = <h1>Hello, world!</h1>;
這個標籤語法既不是字符串也不是HTML,這就是JSX。它是JavaScript的一種擴展語法。前端
咱們先從官網的一個最簡單的例子提及,爲了讓你們可以直接在本地運行,我貼出了完整的代碼以下:java
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> const element = <h1>Hello, world!</h1>; ReactDOM.render( element, document.getElementById('example') ); </script> </body> </html>
你們能夠直接粘貼上面代碼,保存在本地的一個test.html文件裏,雙擊打開後,在瀏覽器裏輸出:node
Hello, world!react
咱們看到git
const element = <h1>Hello, world!</h1>;
element變量的聲明就是用了JSX語法,HTML語言直接寫在JavaScript語言之中,不加任何引號。github
注意:
script
標籤的 type
屬性爲 text/babel
,這是React 獨有的 JSX 語法,跟 JavaScript 不兼容。凡是在頁面中直接使用 JSX 的地方,都要加上 type="text/babel"
。
一共用了三個庫: react.js 、react-dom.js 和 browser.min.js ,它們必須首先加載。其中,react.js 是 React 的核心庫,react-dom.js 是提供與 DOM 相關的功能, browser.min.js的做用是將 JSX 語法轉爲 JavaScript 語法。
好比要建立一個dom超連接:
<a class="link" href="https://github.com/facebook/react">React<a>
咱們在原生DOM中,用js構造dom的方式是這樣的:
var a = document.createElement('a') a.setAttribute('class', 'link') a.setAttribute('href', 'https://github.com/facebook/react') a.appendChild(document.createTextNode('React'))
這個代碼應該是你們比較熟悉的。當你在寫代碼的時候會不會感受很繁瑣呢,咱們能夠封裝一下:
//第一個參數爲node名 //第二個參數爲一個對象,dom屬性與事件都以鍵值對的形式書寫 //第三個到第n個爲子node,它們將按參數順序出現, //在這個例子中只有一個子元素,並且也是文本元素,因此能夠直接書寫,不然還得React.createElement一下 var a = React.createElement('a', { className: 'link', href: 'https://github.com/facebook/react' }, 'React')
看完這個代碼,是否是感受一會兒要簡潔的多。
如今有個編譯工具,可讓你用html語法來寫React.createElement,部署上線前編譯回來。你願意嗎?
無論你的答案是什麼,但這就是jsx的一半真相。
前面已經回答過,在使用React的時候,能夠不使用JSX,大概這樣寫:
var child1 = React.createElement('li', null, 'First Text Content'); var child2 = React.createElement('li', null, 'Second Text Content'); var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
使用這樣的機制,咱們徹底能夠用JavaScript構建完整的界面DOM樹,正如咱們能夠用JavaScript建立真實DOM。但這樣的代碼可讀性並很差,因而React發明了JSX
,利用咱們熟悉的HTML語法來建立虛擬DOM:
var root =( <ul className="my-list"> <li>First Text Content</li> <li>Second Text Content</li> </ul> );
總結
這兩段代碼是徹底等價的,後者將XML語法直接加入到JavaScript代碼中,讓你可以高效的經過代碼而不是模板來定義界面。
以後JSX經過翻譯器轉換到純JavaScript再由瀏覽器執行。
注意
在實際開發中,JSX在產品打包階段都已經編譯成純JavaScript,JSX的語法不會帶來任何性能影響。
另外,因爲JSX只是一種語法,所以JavaScript的關鍵字class, for等也不能出如今XML中,而要如例子中所示,使用className, htmlFor代替,這和原生DOM在JavaScript中的建立也是一致的。
相信你們在看完了上面的這些舉例後,心中的疑問天然而然就迎刃而解了。
所以,JSX自己並非什麼高深的技術,能夠說只是一個比較高級但很直觀的語法糖。它很是有用,卻不是一個必需品,沒有JSX的React也能夠正常工做:只要你樂意用JavaScript代碼去建立這些虛擬DOM元素。
看了上面的這些簡單的demo,你們確定會拋出這樣的疑問:
爲何React官方推薦使用JSX呢?
等等。。。
使用React,不必定非要使用JSX語法,可使用原生的JS進行開發。
可是React做者強烈建議咱們使用JSX,由於:
JSX在定義相似HTML這種樹形結構時,十分的簡單明瞭。
簡明的代碼結構更利於開發和維護。
XML有着開閉標籤,在構建複雜的樹形結構時,比函數調用和對象字面量更易讀。
可能說這些你會感受比較模糊,下面來舉幾個看得見的例子。
前端界面的最基本功能在於展示數據,爲此大多數框架都使用了模板引擎,
<div ng-if="person != null"> Welcome back, <b>{{person.firstName}} {{person.lastName}}</b>! </div> <div ng-if="person == null"> Please log in. </div>
{{#if person}} Welcome back, <b>{{person.firstName}} {{person.lastName}}</b>! {{else}} Please log in. {{/if}}
模板能夠直觀的定義UI來展示Model中的數據,你沒必要手動的去拼出一個很長的HTML字符串,幾乎每種框架都有本身的模板引擎。
傳統MVC框架強調界面展現邏輯和業務邏輯的分離,所以爲了應對複雜的展現邏輯需求,這些模板引擎幾乎都不可避免的須要發展成一門獨立的語言。
如上面代碼所示,每一個框架都有本身的模板語言語法。而這無疑增長了框架的門檻和複雜度。
使用JSX
正由於如此,React直接放棄了模板而發明了JSX。看上去很像模板語言,但其本質是經過代碼來構建界面,這使得咱們再也不須要掌握一門新的語言就能夠直觀的去定義用戶界面:掌握了JavaScript就已經掌握了JSX。
這裏不妨再引用以前文章舉過的例子,在展現一個列表時,模板語言一般提供名爲Repeat的語法,例如在Angular中:
<ul class="unstyled"> <li ng-repeat="todo in todoList.todos"> <input type="checkbox" ng-model="todo.done"> <span class="done-{{todo.done}}">{{todo.text}}</span> </li> </ul>
而使用JSX,則代碼以下:
var lis = this.todoList.todos.map(function (todo) { return ( <li> <input type="checkbox" checked={todo.done}> <span className={'done-' + todo.done}>{todo.text}</span> </li> ); }); var ul = ( <ul class="unstyled"> {lis} </ul> );
能夠看到,JSX完美利用了JavaScript自帶的語法和特性,咱們只要記住HTML只是代碼建立DOM的一種語法形式,就很容易理解JSX。
而這種使用代碼構建界面的方式,徹底消除了業務邏輯和界面元素之間的隔閡,讓代碼更加直觀和易於維護。
你能夠用 花括號 把任意的 JavaScript 表達式 嵌入到 JSX 中。
例如,2 + 2, user.firstName, 和 formatName(user),這些都是可用的表達式。
function formatName(user) { return user.firstName + ' ' + user.lastName; } const user = { firstName: 'Harper', lastName: 'Perez' }; const element = ( <h1> Hello, {formatName(user)}! </h1> ); ReactDOM.render( element, document.getElementById('root') );
編譯以後,JSX 表達式就變成了常規的 JavaScript 對象。
這意味着你能夠在 if 語句或者是 for 循環中使用 JSX,用它給變量賦值,當作參數接收,或者做爲函數的返回值。
function getGreeting(user) { if (user) { return <h1>Hello, {formatName(user)}!</h1>; } return <h1>Hello, Stranger.</h1>; }
您可使用雙引號來指定字符串字面量做爲屬性值:
const element = <div tabIndex="0"></div>;
您也能夠用花括號嵌入一個 JavaScript 表達式做爲屬性值:
const element = <img src={user.avatarUrl}></img>;
注意
在屬性中嵌入 JavaScript 表達式時,不要使用引號來包裹大括號。不然,JSX 將該屬性視爲字符串字面量而不是表達式。
對於字符串值你應該使用引號,對於表達式你應該使用大括號,但二者不能同時用於同一屬性。
若是是空標籤,您應該像 XML 同樣,使用 />當即閉合它:
const element = <img src={user.avatarUrl} />;
JSX 標籤可能包含子元素:
const element = ( <div> <h1>Hello!</h1> <h2>Good to see you here.</h2> </div> );
在JSX中嵌入用戶輸入是安全的:
const title = response.potentiallyMaliciousInput; // This is safe: const element = <h1>{title}</h1>;
默認狀況下, 在渲染以前, React DOM 會格式化(escapes) JSX中的全部值。
從而保證用戶沒法注入任何應用以外的代碼。
在被渲染以前,全部的數據都被轉義成爲了字符串處理。 以免 XSS(跨站腳本) 攻擊。
Babel 將JSX編譯成 React.createElement() 調用。
下面的兩個例子是是徹底相同的:
const element = ( <h1 className="greeting"> Hello, world! </h1> );
const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, world!' );
React.createElement() 會執行一些檢查來幫助你編寫沒有bug的代碼,但基本上它會建立一個以下所示的對象:
// 注意: 這是簡化的結構 const element = { type: 'h1', props: { className: 'greeting', children: 'Hello, world' } };
關於JSX的介紹大概講到這裏,看完這篇文章後,但願你們能可以瞭解什麼是JSX,React爲何推薦使用JSX等問題。
在下一節中來探索如何將 React 元素渲染到 DOM 上。
歡迎你們訪問個人blog,有更精彩的文章吆!
參考連接