React的JSX語法及組件


最近一個同事很急沒有做任何交接就請了陪產假,然后我來維護。說實在的我一開始是一臉懵逼的。因為MV*項目里用的最多的還是Vue;React聽說也了解過,但畢竟不熟。。。

不過不管如何這也是工作;同事也恭喜同事當爸了,打心理為他感到高興!

代碼down下來后開始查看的時候語法基本上使用的都是CMD,ES6還有本文講的JSX,React組件。CMD,ES6這不難畢竟平常也經常用。但是JSX,React組件一開始就有點懵逼,

不過多看幾遍加百度Google就懂了。

(好像廢話有點多,好了,開始講重點....)

首先是JSX:

我一開始看的時候,咦,怎么寫dom不需要引號嗎?后來才知道React發明了JSX利用html語法來創建虛擬dom。這同時也是React的核心之一。可以在內存中創建的虛擬DOM元素。React利用虛擬DOM來減少對實際DOM的操作從而提升性能。類似於真實的原生DOM,虛擬DOM也可以通過JavaScript來創建(React.createElement)

render(){
   return React.createElement('div',null,'content text')  

}

 JSX本身就和XML語法類似,可以定義屬性以及子元素。唯一特殊的是可以用大括號來加入;大括號中的語法就是純JavaScript表達式,返回值會賦予組件的對應屬性,因此可以使用任何JavaScript變量或者函數調用。同時大括號中使用JavaScript表達式來返回需要展現的元素。

 JSX中的事件

JSX采用駝峰寫法來描述事件名稱,大括號中仍然是標准的JavaScript表達式,返回一個事件處理函數。在JSX中你不需要關心什么時機去移除事件綁定,因為React會在對應的真實DOM節點移除時就自動解除了事件綁定。且采用事件代理的模式:在根節點document上為每種事件添加唯一的Listener,然后通過事件的target找到真實的觸發元素。這樣從觸發元素到頂層節點之間的所有節點如果有綁定這個事件,React都會觸發對應的事件處理函數。這就是所謂的React模擬事件系統。盡管整個事件系統由React管理,但是其API和使用方法與原生事件一致。這種機制確保了跨瀏覽器的一致性:在所有瀏覽器(IE8及以上)都可以使用符合W3C標准的API,包括stopPropagation(),preventDefault()等等。對於事件的冒泡(bubble)和捕獲(capture)模式也都完全支持

<button onClick={this.checkAndSubmit.bind(this)}>Submit</button>

    在JSX中使用樣式

在JSX中使用樣式和真實的樣式也很類似,通過style屬性來定義,但和真實DOM不同的是,屬性值不能是字符串而必須為對象,例如:

<div style={{color: '#ff0000', fontSize: '14px'}}>Hello World.</div>

這段JSX中的大括號是雙的,有點奇怪,但實際上里面的大括號只是標准的JavaScript對象表達式,外面的大括號是JSX的語法。所以,樣式你也可以先賦值給一個變量,然后傳進去,代碼會更易讀:

var style = {
  color: '#ff0000',
  fontSize: '14px'
};

var node = <div style={style}>HelloWorld.</div>;

注意:在JSX中可以使用所有的的樣式,基本上屬性名的轉換規范就是將其寫成駝峰寫法,例如“background-color”變為“backgroundColor”, “font-size”變為“fontSize”,這和標准的JavaScript操作DOM樣式的API是一致的。

React自定義組件

首先看一個React官方的demo:

class HelloWorld extends React.Component{
  render() {
    return (
      <p>
        Hello, <input type="text" placeholder="Your name here" />!
        It is {this.props.date.toTimeString()}  {/*通過this.props.data獲取傳過來的數據*/}
      </p>
    );
  }
};

setInterval(function() {
  React.render(
    <HelloWorld date={new Date()} />,
    document.getElementById('example')
  );
}, 500);

 組件的概念和生命周期

React使用組件來封裝界面模塊,整個界面就是一個大組件,開發過程就是不斷優化和拆分界面組件、構造整個組件樹的過程。可以認為組件類似於其他框架中Widget(或Control)的概念,但又有所不同。React中的界面一切皆為組件,而Widget一般只是嵌入到界面中為完成某個功能的獨立模塊。如下圖,整個頁面是一個大的組件,然后再將其拆分成很多小的組件。組件機制加上JSX的語法,讓你在構造界面時就像有一套符合項目需求的HTML標記,界面定義變得非常直觀。

組件自身定義了一組props作為對外接口,每次props改變都能以整體刷新頁面的思路去考慮界面展現邏輯。展示一個組件時只需要指定props作為XML節點的屬性。組件很少需要對外公開方法,唯一的交互途徑就是props。這使得使用組件就像使用函數一樣簡單,給定一個輸入,組件給定一個界面輸出。當給予的參數一定時,那么輸出也是一定的。而傳統控件通常提供很多方法讓你在外部改變控件的狀態和行為,當控件的狀態在不同場景不同邏輯中可以被隨意控制時,開發和調試也會變得復雜。

如果整個項目完全采用React,那么界面上就只有一個組件根節點;如果局部使用React,那么每個局部使用的部分都有一個根節點。在Render時,根節點由React.render函數去觸發:

React.render(
  <App />,
  document.getElementById('react-root')
);

而所有的子節點則都是通過父節點的render方法去構造的。每個組件都會有一個render方法,這個方法返回組件的實例,最終整個界面得到一個虛擬DOM樹,再由React以最高效的方式展現在界面上。

除了props之外,組件還有一個很重要的概念:state。組件規范中定義了setState方法,每次調用時都會更新組件的狀態,觸發render方法。需要注意,render方法是被異步調用的,這可以保證同步的多個setState方法只會觸發一次render,有利於提高性能。和props不同,state是組件的內部狀態,除了初始化時可能由props來決定,之后就完全由組件自身去維護。在組件的整個生命周期中,React強烈不推薦去修改自身的props,因為這會破壞UI和Model的一致性,props只能夠由使用者來決定。

對於自定義組件,唯一必須實現的方法就是render();除此之外,還有一些方法會在組件生命周期中被調用,如下圖所示:

圖中的方法幾乎已經包括了React的所有API,自定義組件時根據需要在組件生命周期的不同階段實現不同的邏輯。除了必須的render方法之外,其它常用的方法包括:

componentDidMount: 在組件第一次render之后調用,這時組件對應的DOM節點已被加入到瀏覽器。在這個方法里可以去實現一些初始化邏輯。

componentWillUnmount: 在DOM節點移除之后被調用,這里可以做一些相關的清理工作。

shouldComponentUpdate: 這是一個和性能非常相關的方法,在每一次render方法之前被調用。它提供了一個機會讓你決定是否要對組件進行實際的render。

shouldComponentUpdate(nextProps, nextState) {
  return nextProps.id !== this.props.id;
}

當此函數返回false時,組件就不會調用render方法從而避免了虛擬DOM的創建和內存中的Diff比較,從而有助於提高性能。當返回true時,則會進行正常的render的邏輯。

組件是React的核心,雖然功能很強大,但是其API和概念卻十分簡單,以至於你只要實現一個render方法就可以創建一個組件。這大大降低了React學習門檻。

參考及原文地址:http://www.infoq.com/cn/articles/react-jsx-and-component/


免責聲明!

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



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