何為JSX?

Pivot發表於2018-06-29

我第一次接觸JSX是在學習React的時候,當時乍一看語法覺得和js很像,在一看又覺得和HTML很像,後期有了專案經驗之後確定jsx確實和那兩位有關係。下面解釋怎麼個有關係法。

一. React元件的構成?

JSX和React有什麼關係呢?簡單說,JSX就是方便React使檢視層(View層)元件化,承載了HTML構建頁面的職責。這點可以看出React還是和其他Js模板語言有著異曲同工之秒的,不同的是React致力於通過建立和更新虛擬元素來管理整個虛擬DOM的(Virtual DOM)。

那什麼是虛擬元素呢,其實就是真實元素的對應,虛擬元素的建立和更新都是在記憶體中完成的,並不會渲染到真正DOM中。虛擬元素分為虛擬DOM和虛擬元件,對應的也就是原生DOM元素和自定義元件。


接著,從DOM元素和自定義元件來解釋:

1.DOM元素

一個很普通的標籤:

<button class="btn btn-blue">
   <em>Confirm</em>
</button>
複製程式碼

上述button標籤包含了元素的型別和屬性,轉換成JSON物件可以更清晰地看見包括元素的型別屬性,即,該標籤是一個DOM元素:

{
  type: 'button',
  props: {
    className: 'btn btn-blue',
    children: {
      type: 'em',
      props: {
        children: 'Confirm'
      }
    }
  }
}
複製程式碼

2.元件元素

上面例項用自定義方法表示為:

const Button = ({color,text}) => {
  return (
    type: 'button',
    props: {
      className: `btn btn-${color}`,
      children: {
        type: 'em',
        props: {
          children: text
        }
      }
    }
  )
}
複製程式碼

該方法用JSON結構描述它為下述,也就是說元件方法的方法名對應了元素的型別,引數對應了元素的屬性,滿足了構造元素的兩大必要條件(元素型別和元素屬性),得出結論:自定義方法也是元素

{
  type: Button,
  props: {
    color: 'blue',
    text: 'Confirm'
  }
}
複製程式碼

用了兩個例子來說明一件事----無論普通標籤還是一個自定義元件方法,都可以用元素表示。這也是React核心思想之一:因為有公共的表達方法,我們可以讓元素們層層巢狀或混合,這些層層巢狀的元件元素就是所謂的React元件,最終我們可以通過遞迴渲染的方式渲染出一整棵DOM樹。

二. JSX由來

構建一個複雜的React元件(還是一個Button元件吧)

(1).首先定義一個元件元素:

const DanderButton = ({text}) => {
  type: Button,
  props: {
    color: 'blue',
    text: text
  }
}
複製程式碼

(2).用上面的組建繼續封裝一個新的元件

const DeleteButton = () => {
  return (
    type: 'div',
    props: {
      children: [
        {
          type: 'p',
          props: {
            children: 'Are you sure?'
          }
        },{
          type: DanderButton,
          props: {
            children: 'Confirm'
          }
        },{
          type: 'Button',
          props: {
            color: 'blue',
            children: 'Cancel'
          }
        }
      ]
    }
  )
}
複製程式碼

這是一個比較簡單的React元件的巢狀,DeleteButton元件清晰地表達了一個功能模組(最外側div)、一段提示語、一個表示確認的按鈕、一個表示取消的按鈕,這麼簡單的功能都已經感覺到很繁瑣了,那麼如果用這種方式去程式設計,感覺會很糟糕,這時讓我們想起了用HTML寫頁面的暢快,JSX寫法應運而生。

同樣是上面的功能,看看JSX是怎麼實現的:

const DeleteButton () => (
  <div>
    <p>Are you sure?</p>
    <DanderButton> Confirm </DanderButton>
    <Buton color="blue">Cancel</Buutton>
  </div>
);
複製程式碼

可見:JSX是將HTML語法加入到Javascript程式碼中,再通過翻譯器轉換成純Javascript後讓瀏覽器執行。實際開發中打包階段都已將編譯成純Javascript程式碼,所以不會帶來任何副作用,反而讓程式碼更加直觀並且易於維護。

現階段為JSX語法解析的編譯器基本上都在用Babel

上述程式碼可以被Babel解析成React可以執行的程式碼

var DeleteButton = function DeleteButton () {
  return React.createElement(
    'div',
    null,
    React.createElement(
      ...
    ),
    React.createElement(
      ...
    ),
    React.createElement(
      ...
    )
  )
}
複製程式碼

可以看出,建立元素時候除了使用React.createElement建立之外,其結構與JSON一樣。

總結:

綜合來看,JSX實質上就是為了方便React將View層元件化,通過將HTMl語法加到Javascript程式碼中,以承擔構建頁面的職責。