- 什麼是jsx?
JSX是JavaScript XML 這兩個單詞的縮寫,xml和html非常類似,簡單來說可以把它理解成使用各種各樣的標籤,大家可以自行 百度。所以jsx就是在javascript中來編寫長得很像xml的語言,這裡只是像,在本質上是不一樣的。
jsx是一種基於Ecmascript的一種新特性,
是一種定義帶屬性樹結構的文法,樹結構就是我們的dom結構,屬性就是dom節點中的屬性,比如所class,id等
jsx不是xml或者Html,
不是一種限制。在react中,我們可以使用jsx來編寫代碼,也可以使用純javascript來編寫代碼,所以說即使你不學jsx也可以正常使用react,但是Facebook官方腿甲使用jsx來編寫。
- 為什麼我們要使用jsx呢?
因為jsx有五個特點
第一個:類xml文法容易接受,在實際的工程中,還有別的人員接觸前端代碼,比如設計師,測試等等,他們很多人可能不熟悉javascript,但是很多人熟悉xml
第二個:增強js的語義,js主要體現在介面的邏輯方面,但是對於介面元素的表現,js是比較弱的,在不使用jsx之前,大部分時候我們使用的是模板,模板其實就是一段字 符串,你在模板裡面寫東西是可以的,模板的問題在於他頁面的內容本身是分離的,並且模板本身是字串,我們很難對其進行擴充,但是jsx是直接在js的基礎上去編寫
html,他的本質並不是字串,就是js語言本身,所以說他可以在語義層面上增強js
第三個:結構清晰,使用jsx來編寫代碼,我們通過代碼就可以知道產生的結果是什麼,就像看html代碼一樣。
第四個:抽象程度高,帶來的第一個好處就是,react屏蔽掉了所有的手動dom操作,之所以能夠屏蔽dom操作,就是因為他像上提供了一個新的抽象層,作為開發人員我們
只需要關注這一個抽象層,而不必關心抽象層下面到底是如何去實現的,從而屏蔽掉了手動的dom操作,抽象帶來的第二個好處就是跨平台,從而誕生了react native。 為什麼可以跨平台呢?你使用jsx去編寫的時候,其實是獨立於平台的文法,你設計是平台本身,react完全可以在不同的平台上提供解譯器,從而可以讓你的代碼執行在不 同的平台上,所以我們說抽象是jsx的核心。
第五個:代碼模組化,在傳統的MVC開發中,MVC其實是分離的,無論是在概念上,還是在實際的代碼上,他們三者往往都不會放在一起,但是在react中,我們發現,編 寫一個組件的時候,他的相關代碼全部都放在了一起,jsx中,既可以js的邏輯,有可以寫頁面的結構,乍一看,好像是不太合適,我們學到的經驗是吧不同的經驗區分出 來,有助於開發的進行。那react將他們都混在了一起,這樣是一個好的選擇嗎?其實react所做的部分是一個橫向的劃分,MVC所做的事情是縱向的劃分,也就是手MVC 把整個項目從上到下切了兩刀,把它切成了三個部分,但是react所做的事情是把一個項目從左至右,切成了很多部分,或者說他既結合了從上到下,又結合了從左至右, 把一個大的項目打散成為了許多小的項目,從而實現代碼的模組化,在代碼的力度變得非常小的時候,我們就可以專註於一個非常具體的功能,在這種情況下,把他們的代 碼都放在一起,更有助於理解,並且有助於代碼本身的組織是,是想一下,如果你把你一個項目拆成了幾十上百個曉得模組,你還要在每一個模組上運用MVC的方法,分 成三個甚至是更多個檔案,那麼這個項目本身就要維護成百上千個檔案了,這是一件非常可怕的事情,所以說在我們討論代碼劃分的合理性時,一定要研究清楚前提條件, 也就是代碼的規模的大小.
- jsx的文法
<script type="text/jsx"> var HelloMessage=React.createClass({ render:function(){ return <div className="test">Hello{this.props.name}</div>; } }); React.render(<HelloMessage name="李明"></HelloMessage>>,mountNode); </script>
看這個例子,很簡單,只是實現了render函數,從上面的代碼中,我們可以看出,jsx其實本質上就是js,他和js的區別就是可以直接在裡面編寫html標籤,這在普通的js中是無法實現的,要想實現只能採用字串的形式來拼接標籤,但是在jsx中,可以原生的支援html標籤。
第一個知識點:HelloMessage,元素名,我們編寫的每一個組件其實也就是一個元素名,這裡我們聲明了一個HelloMessage標籤,在最後一行中,我們將它渲染到了mountNode中,我們可以看到,渲染的時候使用的文法就是標準的html文法,直接在標籤中填寫標籤名,只是這個標籤名是我們自訂出來的。
第二個知識點:就是子節點 this.props.name,標籤和標籤之間可以有嵌套關係,就像我們在html中編寫的一樣,每個標籤都可以嵌套在別的標籤中,他也可以擁有很多的標籤作為他的子節點,在jsx中,jsx和html嵌套不同的一點就是可以在子節點中使用求值運算式,我們可以看到圖中的子節點本質上是一個文本節點,只是這個文本節點有兩部分組成,第一個部分是Hello字串,後面跟一個空格,第二部分是由大括弧括起來的一個運算式,這個運算式所做的事情就是取出這個組件屬性中的,name屬性的值,並把它放在這個節點裡,和hello+空格拼成一個完整的文本節點,至於什麼是屬性,我們後面說。這裡只要知道每個組件都有屬性,也就是props,屬性內部會存很多屬性和屬性名稱。
第三個知識點就是節點屬性,<HelloMessage name="李明"></HelloMessage>,這裡的name就是,我們使用this.props.name來擷取他的值,這個值從哪來呢,就是在使用標籤的時候,我們給定的。
- 補充幾個react文法的關鍵內容。
第一:首字母大小寫。react對於首字母的大小寫是敏感的,如果一個組件的首字母是大寫,那麼react就知道他是一個自訂的組件,如果是小寫,react就會把它當做內建dom的內建元素名,比如說我們上面代碼中的HelloMessage首字母就是大寫,是自訂的組件,後面的div首字母是小寫,因為他是dom中的組件,如果你的自訂群組件首字母是小寫,那麼字啊render渲染的時候會出錯,因為react會去dom中尋找,但是顯然你自訂的組件是不會存在於dom標準組件中,所以就會出錯。
第二:嵌套。組件和組件之間,就像dom和dom之間,可以進行嵌套,上面代碼中我們只進行了一層嵌套,就是在div中嵌套了一個文本節點,其實可以在裡面嵌套各種各樣的無數節點
第三:求值運算式。求值運算式其實和jsx本身是沒有什麼關係的,他是作為js本身的一個特性,js中有幾種文法元素,比如關鍵字,語句,運算式等等,那麼求值運算式是什麼意思?就是他本身是一個運算式,他會返回一個值,這裡我們需要強調的是求值運算式和語句本質上是不一樣的,也就是說,我們在編寫jsx的時候,大括弧裡面,不可以使用語句,比如if語句,for語句,switch語句等,都是不可以的,但是求值運算式可以的,那我們應該如何去區分求值運算式和和語句呢?多個運算式可以聯合使用,但是語句是不可以的,比中的this.props.name是一個字串形式的運算式,他會返回一個字串,我們可以對他進行一些運算,比如說給他加個abc,做字串的加法,把他們連到一起,這是可以的,但是如果是是個if語句,你是不能在if語句進行運算的,語句是不能進行運算的,但是運算式可以,所以區分運算式和語句的方法就是看他能不能進行運算。雖然我們不能直接使用if等語句,但是我們可以把它包裹在函數求值運算式中,從而在函數求值運算式內部來使用這個語句,但是這個函數本身是一個運算式,所以我們可以把它用在jsx的大括弧中,這樣我們就實現了可以在大括弧中運行各種語句,但是在實際使用中,這並不是一個很好的情況,如果有這樣的情況,建議把它獨立出來,然後在大括弧中來調用這個函數。
第四:駝峰命名。jsx標籤使用的是駝峰命名,函數名也是。
第五:兩個特殊的屬性。html的標籤中可以使用html屬性和class屬性,但是我們現在是在js的上下文中區編寫html檔案,html和class是js得保留字和關鍵字,所以我們不能直接把他寫在js中,jsx解決這個問題的辦法就是使用兩個別名來代替他們,也就是htmlFor和className,如果我們要使用html和class屬性,我們實際要寫的是htmlFor和className,在解譯器解釋的時候,會自動把他們一一對應過去,可以看到我們上面的代碼中,div的class就是寫的className。直接使用會報錯。
- jsx文法執行個體---注釋
添加註釋有兩種方法,第一種是多行注釋,使用/**/,第二種是單行注釋,使用//,
注釋可以放在兩個部分。
第一個部分:子節點中,也就是標籤包裹的這一部分,這裡需要使用大括弧來包裹注釋。下面的代碼中,HelloWorld後面。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>hello world</title></head><body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var HelloWorld=React.createClass({ render: function(){ return <p>Hello,world{ /* 這是一個多行注釋 */ //這是一個單行注釋 }</p> } }); React.render(<HelloWorld></HelloWorld>,document.body); </script></body></html>
第二個部分:屬性中,也就是標籤本身這裡
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>hello world</title></head><body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var HelloWorld=React.createClass({ render: function(){ return <p /* 這是一個注釋 */ name="李明"//這裡是一個屬性,單行注釋也可以和屬性放在同一行 //這是一個單行注釋 >Hello,world { /* 這是一個多行注釋,放在了子節點中 */ "Jerry"//他是字串,由於被包裹在大括弧中,本身應該是js,所以應該用雙引號包裹 //我是單行注釋 } </p> } }); React.render(<HelloWorld></HelloWorld>,document.body); </script></body></html>
- jsx文法執行個體--如何在jsx裡面書寫css樣式。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>hello world</title></head><body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var HelloWorld=React.createClass({ render: function(){ return <p>Hello,world</p> } }); React.render(<div style={style}><HelloWorld></HelloWorld></div>,document.body); </script></body></html>
需要注意的是其他屬性的賦值一般是字串,但是style 屬性的賦值一般是一個對象,這是因為style屬性比較特殊,react會把style裡面自訂的屬性,正確的應用到style上面,
React.render(<div style={style}><HelloWorld></HelloWorld></div>,document.body);
- jsx文法執行個體:嵌套
6中的執行個體就有示範,如下代碼
React.render(<div style={style}><HelloWorld></HelloWorld></div>,document.body);
我們將我們的自訂群組件HelloWorld放到了div中,實際開發中,我們可以嵌套無數個。
- 條件判讀的四種寫法
if語句不是一個運算式,他是一個語句,所以說在編寫jsx代碼的時候,我們不能直接使用if語句,但是我們可以使用四種運算式來實現相同的效果
我們實現這個功能,如果傳入屬性name的值,我們就輸出name的值,如果沒有,我們就輸出world
8.1使用三元運算式
如果我們直接使用 if....else語句會直接報錯,代碼如下。
點擊查看代碼
所以這裡我們使用三元運算式,如下代碼,可以吧HelloWorld裡,name的屬性去掉以後,在看看效果
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>hello world</title></head><body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var HelloWorld=React.createClass({ render: function(){ return <p>Hello,{this.props.name ? this.props.name : "world"}</p> } }); React.render(<div style={style}><HelloWorld name="李明"></HelloWorld></div>,document.body); </script></body></html>
8.2使用一個變數,我們通過函數來個這個變數賦值,最後把變數的值直接用在大括弧裡。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>hello world</title></head><body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var HelloWorld=React.createClass({ getName:function(){ if(this.props.name) return this.props.name else return "world" },//這裡有逗號,切記 render: function(){ var name=this.getName(); return <p>Hello,{name}</p> } }); React.render(<div style={style}><HelloWorld name="李明"></HelloWorld></div>,document.body); </script></body></html>
8.3改8.2中的例子,直接把大括弧去掉,直接調用
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>hello world</title></head><body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var HelloWorld=React.createClass({ getName:function(){ if(this.props.name) return this.props.name else return "world" },//這裡的逗號 render: function(){ return <p>Hello,{this.getName()}</p> } }); React.render(<div style={style}><HelloWorld name="李明"></HelloWorld></div>,document.body); </script></body></html>
8.4使用比較計算符
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>hello world</title></head><body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var HelloWorld=React.createClass({ render: function(){ return <p>Hello,{this.props.name || "world"}</p> } }); React.render(<div style={style}><HelloWorld name="李明"></HelloWorld></div>,document.body); </script></body></html>
- 萬能的函數運算式
通常情況下,函式宣告並不是一個運算式,而是一個語句,但是我們可以通過特殊的方式,將它改成運算式,從而可以直接調用函數擷取傳回值,由於他是一個運算式,我們可以把它用在大括弧中,我們看下面的例子。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>hello world</title></head><body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var HelloWorld=React.createClass({ render: function(){ return <p>Hello,{ (function(obj){ if(obj.props.name) return obj.props.name else return "world" })(this) }</p> } }); React.render(<div style={style}><HelloWorld name="李明"></HelloWorld></div>,document.body); </script></body></html>
這個例子要注意理解強制求值運算,也就是把function包裹起來的那個括弧,在這個括弧裡面的function會被強制求值運算,他會返回一個函數的引用,然後我們又在後面加了一個(this),用()來調用他, 並傳入一個this,就可以實現我們想要的效果
(function(obj){ })(this)
這個括弧還有一種寫法,就是把(this)前面的括弧放到後面,具體看代碼,也是可以的。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>hello world</title></head><body> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/react.js"></script> <script type="text/javascript" src="http://cdn.bootcss.com/react/0.13.2/JSXTransformer.js"></script> <script type="text/jsx"> var style={ color:"red", border:"1px solid #f09", }; var HelloWorld=React.createClass({ render: function(){ return <p>Hello,{ (function(obj){ if(obj.props.name) return obj.props.name else return "world" }(this)) }</p> } }); React.render(<div style={style}><HelloWorld name="李明"></HelloWorld></div>,document.body); </script></body></html>
括弧放在外面和裡面的區別,放在裡面的時候,括弧執行完畢拿到的是函數的引用,然後在調用他,但是括弧放在外面的時候,弄到的直接就是傳回值,而不是函數引用本身。建議大家看看this的用法。