[轉] ReactJS之JSX語法


JSX 語法的本質目的是為了使用基於 xml 的方式表達組件的嵌套,保持和 HTML 一致的結構,語法上除了在描述組件上比較特別以外,其它和普通的 Javascript 沒有區別。 並且最終所有的 JSX 都會編譯為原生 Javascript。

JSX = JavaScript XML
JSX 是一個看起來很像 XML 的 JavaScript 語法擴展。

特點

  • 類XML語法:有固定的標簽開啟和閉合。這能讓復雜的樹更易於閱讀,優於方法調用和對象字面量的形式。
  • 增強JS語義:不是模板,模板與頁面是分離的,是字符串,而JSX是JS語法本身,有更多的擴展
  • 結構清晰
  • 抽象程度高:屏蔽了手動的DOM操作,跨平台-JSX是獨立於平台的語法,React在不同的平台提供解釋器
  • 代碼模塊化:MVC是縱向切分,React是橫向切分,大項目由眾多小項目組成

HTML組件 與 React組件

HTML組件和HTML中原生的組件一樣,而React組件是自定義的組件
JSX 中約定以大小寫字母開頭來區分,組件一般以大寫字母開頭

//JSX中支持絕大部分HTML標簽
<label className="lb" htmlfor="uName" style={{color:'red'; font-size:'14px'}}></label>

// 組件類
class MyComponent extends React.Component{
render(){
return <div>Customer Component:{this.props.name}</div>
}
}

React.render(<MyComponent name="propsText"/>, document.getElementById('d1'))

由於 JSX 就是 JavaScript,一些標識符像 class 和 for 不建議作為 XML 屬性名。作為替代,React DOM 使用 className 和 htmlFor 來做對應的屬性。

JSX轉換器

JSX 把類 XML 的語法轉成純粹 JavaScript,XML 元素、屬性和子節點被轉換成 React.createElement 的參數。

React.createElement(HTML標簽名稱/父組件,標簽屬性,子元素)

//JSX語法
<label className="xxx" htmlFor="input">content</label>

//轉換后
React.createElement('label', {className: 'xxx', htmlFor: 'input'}, 'content')

命名空間式組件

如果一個組件擁有多個子組件,可以將子組件做為父組件的屬性

// 命令空間式組件
class FormRoot extends React.Component{
render(){
return(
<div>
FromRoot
{this.props.children}
</div>
)
}
}

class Row extends React.Component{
render(){
return(
<div className="box" style={{color:'#3f3', height:'auto'}}>
Form Row {this.props.children}
</div>
)
}
}
class Label extends React.Component{
render(){
return <div className="box" style={{color:'#f90'}}> Form Label </div>
}
}
class Input extends React.Component{
render(){
return <div className="box" style={{color:'red'}}> Form Input </div>
}
}

FormRoot.Row = Row;
FormRoot.Label = Label;
FormRoot.Input = Input;

class APP extends React.Component{
render(){
return (
<div className="box" style={{height:'auto'}}>
<FormRoot>
<FormRoot.Row>
<FormRoot.Label />
<FormRoot.Input />
</FormRoot.Row>
</FormRoot>
</div>
)
}
}

React.render(<APP />, document.getElementById('box1'));

Javascript表達式

在JSX語法中,使用{}標識內部是JS表達式
JSX是HTML和JavaScript混寫的語法,當遇到<,JSX就當HTML解析,遇到{就當Javascript解析

render(){
return <Person name={window.isLoggedIn ? window.name : ''} />
}

屬性表達式

在使用 JS表達式 做為屬性時,必須使用 {} 包含在內,不可使用 ""

render(){
return <div className={2 > 1 ? 'class-a' : 'class-b'}>content</div>
}

子表達式

組件嵌套中同樣可以使用 JS表達式 來處理組件的顯示邏輯

render(){
return <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>
}

注釋 (Comments)

注釋作用於源碼,對源碼做說明,不會出現實在渲染后的DOM中

var content = (
<div className="box">
{/* 一般注釋, 用 {} 包圍 */}
<span
/* 多

注釋 */
name={2>1 ? '2' : '1'} // 行尾注釋
>{2>1 ? '2' : '1'}</span>
</div>
);

React.render(content, document.getElementById('box1'));

延展屬性(Spread Attributes)

組件的屬性應當在組件初始化時指定,而不應在初始化以后指定,這樣會導致 props 對象的修改不可預測, React 也不能幫助檢查屬性類型。

//better
<Component foo={x} bar={y} />

//bad
<Component />
Component.props.foo = x;
Component.props.bar = y;

屬性延展是將一個對象添加為組件的屬性的語法糖
操作符 ... 是ES6中的延展語法(spread operator),可以將一個對象展開

var props = { foo: x, bar: y };
var component = <Component { ...props } foo={'override'}>;

// 等價於
var component = <Component foo={x} bar={y} />;

注意:后面相同的屬性覆蓋掉前面的屬性

JSX陷阱

style屬性

style屬性是用兩個 { 包含的,最外層的 { 表示內部是一個JS表達式,里面的 { 表示是一個JS對象字面量

render(){
return (
<div style={{color:'red'}}>
xxxxx
</div>
)

}

HTML轉義

React 默認會轉義所有字符串,為了防止各種 XSS 攻擊。
可使用 __html 進行轉義

var content='<strong>content</strong>';

React.render(
<div>{content}</div>,
document.body
);
//頁面直接輸出: <strong>content</strong>


var content='<strong>content</strong>';

React.render(
<div dangerouslySetInnerHTML={{__html: content}}></div>,
document.body
);

//輸出加粗后的: content

標簽閉合

在JSX中,無論是單標簽還是成對的雙標簽,必有閉合符,不然會報錯

render(){
return(
<div>
<img src="xxx.jpg" />
<button>確認<button/>
</div>
)
}

根節點

自定義組件在render()函數中返回的組件內容,必須有一個根節點包含起來

// bad
function render() {
return (<p> .... </p>
<p> .... </p>)
}
// good
function render() {
return (<p> .... </p>)
}

function render() {
return (
<div>
<p> .... </p>
<p> .... </p>
</div>
)
}

循環遍歷

通過循環遍歷出生成的組件集合,在循環時一定要加上key


render(){
return (
<p>
{arr.map(function(it,i) {
return <span key={i}> {it} </span>
})}
</p>
)
}

IF-ELSE

在JSX中是不可以直接在{}中加入if-else

  • 使用 三元操作符 來替代 if-else,或者將復雜的操作在JSX外面使用JS去處理
  • 使用閉包自執行函數
//錯誤的寫法
// var App = (
// <div>
// {
// if(2>1){
// <p>SUCCESS</p>
// }else{
// <p>FAILURE</p>
// }
// }
// </div>
// );

var App = (
<div className="box">
{
2>1 ? <p>SUCCESS</p> : <p>FAILURE</p>
}
</div>
);

React.render(App, document.getElementById('box1'))


// 或者
// 將邏輯抽離到JS中執行
var loginButton;
if (loggedIn) {
loginButton = <LogoutButton />;
} else {
loginButton = <LoginButton />;
}

return (
<nav>
<Home />
{loginButton}
</nav>
);

// 或者
// 使用閉包自執行函數
var App = (
<div className="box">
{
(()=>{
if(2>1){
return <p>SUCCESS</p>
}else{
return <p>FAILURE</p>
}
})()
}
</div>
);

Show-Hide

class App extends React.Component{
constructor(){
super()
this.state={
showHide: true
}
}
render(){
return (
<div className="box" style={{heigth:'auto'}}>
<div className={this.props.showHide?"":"hide"}>通過Props可以初始化這段文字的顯示隱藏</div>
<div className={this.state.showHide?"":"hide"}>通過State可以改變這段文字的顯示隱藏</div>
<input type="button"
value={this.state.showHide ? '隱藏':'顯示'}
onClick={()=>{ this.setState({showHide : !this.state.showHide}) }}
/>
</div>
)
}
}

React.render(<App showHide={true} />, document.getElementById('box1'))

Switch-Case

return (
<section>
<h1>Color</h1>
<h3>Name</h3>
<p>{this.state.color || "white"}</p>
<h3>Hex</h3>
<p>
{(() => {
switch (this.state.color) {
case "red": return "#FF0000";
case "green": return "#00FF00";
case "blue": return "#0000FF";
default: return "#FFFFFF";
}
})()}
</p>
</section>
);

Loop:循環

var rows = [];
for (var i=0; i < numrows; i++) {
rows.push(<ObjectRow key={i}/>);
}

render(){
return (<tbody>{rows}</tbody>);
}

相關示例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM