JSX語法,像是在Javascript代碼裏直接寫XML的語法,實質上這只是一個語法糖,每一個XML標籤都會被JSX轉換工具轉換成純Javascript代碼,React 官方推薦使用JSX, 當然你想直接使用純Javascript代碼寫也是可以的,只是使用JSX,組件的結構和組件之間的關係看上去更加清晰。
1. HTML 標籤 和 React 組件
在JS中寫HTML標籤,也許小夥伴們都驚呆了,那麼React又是怎麼區分HTML標籤,React組件標籤?
HTML標籤:
var myDivElement = ; React.render(myDivElement, document.body);
React組件標籤:
var Div= React.createClass({/*...*/});
var myElement = << span="">Div someProperty={true} />;
React.render(myElement, document.body);
插播:
1. 注意大寫開頭*
2. 不要隨意document.body, 它是覆蓋不是追加。(及時代碼找的回來)
3. 屬性someProperty={true}
是不是很簡單,一眼就發現了,congruatulations 聰明的你已經理解!
2. JSX與原生態JavaScript
//使用JSX React.render( content, document.getElementById('example') ); //不使用JSX React.render( React.createElement('div', null, React.createElement('div', null, React.createElement('div', null, 'content') ) ), document.getElementById('example') );
那麼也就是說,我們寫一個XML標籤,實質上就是在調用 React.createElement
這個方法,並返回一個 ReactElement
對象。
API中:
React.createElement
ReactElement createElement( string/ReactClass type, [object props], [children ...]) #注意此處的省略號
第一個參數可以是一個字符串,表示是一個HTML標準內的元素,或者是一個ReactClass類型的對象,表示我們之前封裝好的自定義組件。
第二個參數是一個對象,或者說是字典也可以,它保存了這個元素的所有固有屬性(即傳入後基本不會改變的值)。
從第三個參數開始,之後的參數都被認作是元素的子元素。
JSX的轉換
React JSX 將元素的標籤、屬性和子元素都會被當作參數傳給 React.createElement
方法:
// JSX var Nav; var app = ; // native JS var Nav; var app = React.createElement(Nav, {color:"blue"});
JSX的轉化器
這個工具會把使用JSX語法的文件轉換成純的可以直接在瀏覽器裏面運行起來的JavaScript文件。它也會爲你監視目錄,然後自動轉換變化的文件
要把帶有JSX語法的代碼轉化爲純Javascript代碼,有多種方式:
1. 對於內聯與HTML中的代碼或者是未經過轉化的外部文件,在 script 標籤中要加上 type="text/jsx" ,並引入 JSXTransformer.js 文件即可。
2. 不過這種方式並不建議在生產環境使用,建議的方法是在代碼上線前就將代碼轉換好,可以使用npm 全局安裝 react-tools :
#npm install react-tools -g
並使用命令行工具轉化即可(具體用法可以參考 jsx -h 或者 jsx --help
) jsx 通過watch實時監控,具體使用看幫助吧。此處只列舉試例:
# jsx --watch src/ build/
( #表示linux中的用戶權限,windows用戶大可不用理睬 )
大愛無邊的React. render
React.render方法可以渲染HTML結構,也可以渲染React組件。
(此處與上面重複,只做演示)
渲染HTML標籤,聲明變量採用 首字母小寫
var myDivElement = ; React.render(myDivElement, document.body);
2. 渲染React組件,聲明變量採用 首字母大寫
var MyComponent = React.createClass({/*...*/}); var myElement = ; React.render(myElement, document.body);
不過需要注意的是 class
和 for
屬性(不太確定多少個,等查閱api後續增加),JSX語法最終是要被轉換爲純Javascript的,所以要和在Javascript DOM中一樣, 用className
和 htmlFor
。
//使用JSX React.render( content, document.getElementById('example') ); //不使用JSX React.render( React.createElement('label', {className: 'xxx', htmlFor: 'input'}, 'content'), document.getElementById('example') );
相信你一眼就瞅出了不同點。
可惡但有可愛之處:
在創建HTML標準內的元素時,JSX轉化器會丟棄那些非標準的屬性,如果一定要添加自定義屬性,那麼需要在這些自定義屬性之前添加 data-
前綴。
上同樣的代碼:
var HtmlOptions = React.createClass({ render:function (){ return ( 屬性延伸 ); } }); var ys = ; React.render(ys, document.getElementById('htmls'));
渲染後,看看你的標籤總是否有zz的屬性,恭喜你........
是不是沒有? 哈哈,那就對了, 把zz替換成data-zz試試。
看上去高大上的用法(捂住)
有人說,用了這些寫法後,不會再寫原生態的JS代碼了, 是的,懶(和)做(諧)纔會是天朝。
比如開發組件的時候,一個組件有多個子組件,你希望這些子組件可以作爲其父組件的屬性,那麼可以像這樣用:
var Form = MyFormComponent; var App = ( );
插播: 此處又要插播了(這是我們的愛好,插播才能提升質量)
React 組件標籤
這樣的寫法表示 自閉合標籤(
)
還要注意:都要開頭大寫,並且加上父類組件標籤哦。爲啥呢? follow
這樣你只需將子組件的 ReactClass 作爲其父組件的屬性:
var MyFormComponent = React.createClass({ ... }); MyFormComponent.Row = React.createClass({ ... }); MyFormComponent.Label = React.createClass({ ... }); MyFormComponent.Input = React.createClass({ ... });
利用子組件 和 父組件形式 再來渲染。
然而這也是可以的:
var App = ( React.createElement(Form, null, React.createElement(Form.Row, null, React.createElement(Form.Label, null), React.createElement(Form.Input, null) ) ) );
該功能需要0.11及以上版本
Javascript表達式
在JSX語法中寫Javascript表達式只需要用 {}
即可,比如下面這個使用三目運算符的例子:
JSX是HTML和JavaScript混寫的語法,當遇到 <
,JSX就當HTML解析,遇到 {
就當JavaScript解析。
// 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) );
屬性表達式
React.render( <div className={2 > 1 ? 'class-a' : 'class-b'}>content</div>, document.body );
子表達式
var Nav = React.createClass({ render: function () { return <div>nav</div> } }); React.render( <div> {2 > 1 ? <Nav/> : <div>div</div>} </div>, document.body );
臥去, so easy!是不是?
相信你會想到這樣寫更碉堡。
// This JSX: <div id={if (condition) { 'msg' }}>Hello World!</div> // Is transformed to this JS: React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");
多高大上啊。可惜是錯誤的
這讓我想起了PHP中html與php混淆的寫法。
<div><?php if ( 1>0 ){ echo '碉堡了'; } ?></div>
或者Pyhon中
[x+n for x in range(0,100) for n in range(0,10) if x%3==0 if n%5==0 ]
看不懂,超碉堡啊! CAO, 是難看,不是看着難。
可以從轉化後的Javascript代碼中看出明顯的語法錯誤,所以要不用三目運算符,要不就這樣寫:
if (condition) <div id='msg'>Hello World!</div> else <div>Hello World!</div>
以下純屬賦值粘貼: 但經過驗證,很不錯
傳播屬性(Spread Attributes)
如果提前就知道了組件的屬性的話,寫起來很容易。例如component組件有兩個動態的屬性foo和bar:
var component = <Component foo={x} bar={y} />;
而實際上,有些屬性可能是後續添加的,我們沒辦法一開始就確定,我們可能會寫出下面不好的代碼:
var component = <Component />; component.props.foo = x; // bad component.props.bar = y; // also bad
這樣寫是錯誤的,因爲我們手動直接添加的屬性React後續沒辦法檢查到屬性類型錯誤,也就是說,當我們手動添加的屬性發生類型錯誤時,在控制檯是看不到錯誤信息的。
在React的設定中,初始化完props後,props是不可變的。改變props會引起無法想象的後果。
延伸屬性
爲了解決這個問題,React引入了屬性延伸
var props = {}; props.foo = x; props.bar = y; var component = <Component {...props} />; //或者 var props = { foo: x, bar: y }; var component = <Component { ...props } />;
這樣就相當於:
var component = <Component foo={x} bar={y} />
當需要拓展我們的屬性的時候,定義個一個屬性對象,並通過 {…props} 的方式引入,在JSX中,可以使用 ...
運算符,表示將一個對象的鍵值對與 ReactElement
的 props
屬性合併,這個 ...
運算符的實現類似於ES6 Array中的 ...
運算符的特性。,React會幫我們拷貝到組件的props屬性中。重要的是—這個過程是由React操控的,不是手動添賦值的屬性。
它也可以和普通的XML屬性混合使用,需要同名屬性,後者將覆蓋前者:
var props = { foo: 'default' }; var component = <Component {...props} foo={'override'} />; console.log(component.props.foo); // 'override'
JSX 陷阱
style屬性
在React中寫行內樣式時,要這樣寫,不能採用引號的書寫方式
React.render( <div style={{color:'red'}}> xxxxx </div>, document.body );
HTML轉義
比如我們有一些內容是用戶輸入的富文本,從後臺取到數據後展示在頁面上,希望展示相應的樣式.
var content='<strong>content</strong>'; React.render( <div>{content}</div>, document.body );
結果頁面直接輸出內容了:
<strong>content</strong>
React默認會進行HTML的轉義,避免XSS***,如果要不轉義,可以這麼寫:
var content='<strong>content</strong>'; React.render( <div dangerouslySetInnerHTML={{__html: content}}></div>, document.body );
最後推薦一個的博文博客:(沒有看,大家可參考閱讀)
http://blog.csdn.net/lihongxun945/article/details/45826851
http://blog.csdn.net/lihongxun945/article/category/5195241
阮一峯的react.js入門