JSX即Javascrpt XML— — 一種在React組件內部構建標籤的類XML文法。
JSX並不是新語言,也沒有改變JavaScript的文法,只是一種基於ECMAScript的新特性,一種定義帶屬性樹結構(DOM結構)的文法
React 可以不使用 JSX 來編寫組件,但是使用 JSX 可以讓代碼可讀性更高、語義更清晰、對 React 元素進行抽象等等。 一、使用JSX好處
1、允許使用熟悉的文法來定義HTML元素樹 2、提供了更加語義化且易懂的標籤
3、程式結構更容易被直觀化 4、抽象了React Element的建立過程
5、可以隨時掌控HTML標籤以及產生這些標籤的代碼 63、是原生Javascript
使用JSX和不使用JSX的代碼對比如下:
//開閉標籤,在構建複雜的樹形結構時,比函數調用和對象字面量更易讀//#使用JSX<div className="red">Children Text</div>;<MyCounter count={3 + 5} />;// 此處給一個js對象設定"scores"屬性var gameScores = { player1: 2, player2: 5};<DashboardUnit data-index="2"> <h1>Scores</h1> <Scoreboard className="results" scores={gameScores} /></DashboardUnit>;//#不使用JSXReact.createElement("div", { className: "red" }, "Children Text");React.createElement(MyCounter, { count: 3 + 5 });React.createElement( DashboardUnit, { "data-index": "2" }, React.createElement("h1", null, "Scores"), React.createElement(Scoreboard, { className: "results", scores: gameScores }));
二、JSX 文法
【注意】 JSX代碼需經babel 編譯成javscript,目前主流瀏覽器才能正常識別,即在head中需添加:
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script>
React還需依賴的另外2個檔案:react.js 是 React 的核心庫,react-dom.js 是提供與 DOM 相關的功能,
並將JSX代碼放在<script type='text/babel'> … </script>中編寫
<!DOCTYPE html><html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> <script src="build/react.js"></script> <script src="build/react-dom.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"> ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('example') ); </script> </body></html>
【推廣】上面必需核心庫找不到的話,可以上本人github下載:https://github.com/mqy1023/react-basejs
JSX是HTML和JavaScript混寫的文法,當遇到<JSX就當HTML解析,遇到 { 就當JavaScript解析。
var names = ['Alice', 'Emily', 'Kate'];ReactDOM.render( <div> { names.map(function (name) { return <div>Hello, {name}!</div> }) } </div>, document.getElementById('example'));
理解Array.prototype.map,返回一個新的數組
var friends = ['Jake Lingwall', 'Murphy Randall', 'Merrick Christensen'];var listItems = friends.map(function(friend){ return "<li> " + friend + "</li>";});console.log(listItems); // ["<li> Jake Lingwall</li>", "<li> Murphy Randall</li>", "<li> Merrick Christensen</li>"];
JSX 允許直接在模板插入 JavaScript 變數。如果這個變數是一個數組,則會展開這個數組的所有成員
// arr變數是一個數組,結果 JSX 會把它的所有成員,添加到模板var arr = [ <h1>Hello world!</h1>, <h2>React is awesome</h2>,];ReactDOM.render( <div>{arr}</div>, document.getElementById('example'));
在React中,一個組件的HTML標籤與產生這些標籤的代碼內在地緊密聯絡在一起。這意味和我們可以輕鬆地利用Javascript強大魔力
1、使用三目運算子
render: function() { return <div className={this.state.isComplete ? 'is-complete' : ''}>...</div>;}
2、使用變數/函數
getIsComplete: function() { return this.state.isComplete ? 'is-complete' : '';},render: function() { var isComplete = this.getIsComplete(); return <div className={isComplete}>...</div>; //或者直接返回函數 return <div className={this.getIsComplete()}>...</div>;}
3、使用邏輯與(&&)或者邏輯或( || )運算子
由於對於null或false值React不會輸出任何內容,因此可以使用一個後面跟隨了期望字串的布爾值來實現條件判斷。如果這個布爾值為true,後續字串會被使用
render: function() { return <div className={this.state.isComplete && 'is-complete'}>...</div>;}
邏輯或,this.props.name為空白時,className值等於is-complete
render: function() { return <div className={this.props.name || 'is-complete'}>...</div>;}
4、函數調用
var HelloWorld = React.createClass({ render: function () { return <p>Hello, {(function (obj) { return obj.props.name ? obj.props.name : "World"; })(this)}</p> }});
三、建立並渲染組件
//1、React.createClass 是用來建立一個組件var HelloMessage = React.createClass({ render: function() { return <h1>Hello {this.props.name}</h1>; }});//2、ReactDOM.render渲染組件ReactDOM.render( <HelloMessage name="John" />, document.getElementById('example'));
一、渲染HTML標籤和React組件
React.render方法可以渲染HTML結構,也可以渲染React組件。
1、渲染HTML標籤,聲明變數採用首字母小寫
var myDivElement = <div className="foo" />;ReactDOM.render(myDivElement, document.body);
2、渲染React組件,聲明變數採用首字母大寫
var MyComponent = React.createClass({/*...*/});var myElement = <MyComponent someProperty={true} />;ReactDOM.render(myElement, document.body);
二、非DOM屬性
1、鍵(key)
key是一個可選的唯一識別碼,當兩個已經在於DOM中的組件交換位置時,React能夠匹配對應的key並進行相應的移動,且不需要完全重新渲染DOM,提供渲染效能
2、引用(ref)
ref允許父組件在render方法之外保持對子組件的一個引用。在JSX中,你可以通過屬性中設定期望的引用名來定義一個引用。
render: function() { return <div> <input ref="myInput" ...> </input> </div> );}
然後你可以在組件的任何地方使用this.refs.myInput擷取這個引用了。通過引用擷取到的這個對象被稱為支援執行個體。它並不是真的DOM,而是React在需要時用來建立DOM的一個描述對象。你可以使用this.refs.myInput.getDOMNode()訪問真實的DOM節點。
3、設定原始的HTML
比如我們有一些內容是使用者輸入的富文本,希望展示相應的樣式
var content='<strong>content</strong>';ReactDOM.render( <div>{content}</div>, document.body);
結果頁面直接輸出內容了:
React預設會進行HTML的轉義,避免XSS攻擊,如果要不轉義,可以這麼寫:
ReactDOM.render( <div dangerouslySetInnerHTML={{__html: "<strong>content</strong>"}}></div>, document.body);
三、事件
在所有的瀏覽器中,事件名已經被正常化並統一用onXXX駝峰形式表示
var BannerAd = React.createClass({ handleClick: function(event) { //... }, render: function() { return <div onClick={this.handleClick}>Click Me!</div>; }})
【注意】 React自動綁定了組件所有方法的範圍,因此你不需要手動綁定
handleClick: function(event) {...},render: function() { //反模式 ————在React中手動給組件執行個體綁定 //函數範圍是沒有必要的 return <div onClick={this.handleClick.bind(this)}>...</div>;}
四、特殊屬性
由於JSX會轉換為原生的Javascript函數,因此有一些關鍵詞我們是不能用的——如class和for,對應JSX中屬性寫成className和htmlFor
//#使用JSXReactDOM.render( <label className="xxx" htmlFor="input">content</label>, document.getElementById('example'));//#不使用JSXReactDOM.render( React.createElement('label', {className: 'xxx', htmlFor: 'input'}, 'content'), document.getElementById('example'));
五、style樣式
React把所有的內聯樣式都正常化為駝峰形式,與Javascript中DOM的sytle屬性一致。第一重大括弧表示這是 JavaScript 文法,第二重大括弧表示樣式對象。
React.render( <div style={{color:'red'}}> xxxxx </div>, document.body);////////////////////////////var style = { color:'red', borderColor: '#999'}ReactDOM.render(<div style={style}>xxxxx</div>, document.body);
六、注釋
JSX本質就是Javascript,因此你可以在標籤內添加原生的javascript注釋。 注釋兩種形式
當作一個元素的子節點 內聯在元素的屬性中
var content = ( <Nav> {/* 一般注釋, 用 {} 包圍 */} <Person /* 多 行 注釋 */ name={window.isLoggedIn ? window.name : ''} // 行章節附註釋 /> </Nav>);
一、不要改變props
如果提前就知道了組件的屬性的話,寫起來很容易。例如component組件有兩個動態屬性foo和bar:
var component = <Component foo={x} bar={y} />;
而實際上,有些屬性可能是後續添加的,我們沒辦法一開始就確定,我們可能會寫出下面不好的代碼:
var component = <Component />;component.props.foo = x; // badcomponent.props.bar = y; // also bad
這樣寫是錯誤的,因為我們手動直接添加的屬性React後續沒辦法檢查到屬性類型錯誤,也就是說,當我們手動添加的屬性發生類型錯誤時,在控制台是看不到錯誤資訊的。
在React的設定中,初始化完props後,props是不可變的。改變props會引起無法想象的後果。 二、延伸屬性
為瞭解決這個問題,React引入了屬性延伸
var props = {};props.foo = x;props.bar = y;var component = <Component {...props} />;
當需要拓展我們的屬性的時候,定義個一個屬性對象,並通過{...props}的方式引入,React會幫我們拷貝到組件的props屬性中。重要的是—這個過程是由React操控的,不是手動添賦值的屬性。
需要覆蓋的時候可以這樣寫:
var props = { foo: 'default' };var component = <Component {...props} foo={'override'} />;console.log(component.props.foo); // 'override'
一、自訂HTML 屬性
如果往原生 HTML 元素裡傳入 HTML 規範裡不存在的屬性,React 不會顯示它們。
ReactDOM.render( <div dd='xxx'>content</div>, document.body);
如果需要使用自訂屬性,要加 data- 首碼。
ReactDOM.render( <div data-dd='xxx' aria-dd='xxx'>content</div>, document.body);
二、組件render渲染函數中return注意點
如果return和JSX語句開頭在同一行時,不需要括弧;否則要括弧包裹
//正確寫法1var HelloMessage = React.createClass({ render: function() { return <h1> Hello {this.props.name}</h1>; }});//正確寫法2render: function() { return <h1>Hello {this.props.name}</h1>;}//正確寫法3render: function() { return ( <h1>Hello {this.props.name}</h1>);}//錯誤寫法render: function() { return <h1>Hello {this.props.name}</h1>;}
參考連結:
1、《React學習筆記—JSX》https://segmentfault.com/a/1190000002646155
2、《React引領未來的使用者介面開發架構》
3、http://facebook.github.io/react/docs/jsx-in-depth.html
4、http://www.jikexueyuan.com/course/969_3.html?ss=1
5、http://buildwithreact.com/tutorial/jsx