React之JSX語法

1.認識JSX的語法

下面是一段JSX語法數組

<script type="text/babel">
  const element = <h2>Hello World</h2>
 ReactDOM.render(element, document.getElementById("app"));
</script>
複製代碼

JSX是什麼?bash

  • JSX是一種JavaScript的語法擴展(eXtension),也在不少地方稱之爲JavaScript XML,由於看起就是一段XML語法;
  • 它用於描述咱們的UI界面,而且其徹底能夠和JavaScript融合在一塊兒使用.(因此靈活性很高);
  • 它不一樣於Vue中的模塊語法,你不須要專門學習模塊語法中的一些指令(好比v-for、v-if、v-else、v-bind);

爲何React選擇了JSX?babel

  • React認爲渲染邏輯本質上與其餘UI邏輯存在內在耦合app

    • 好比UI須要綁定事件(button、a原生等等);
    • 好比UI中須要展現數據狀態,在某些狀態發生改變時,又須要改變UI;
  • 他們之間是密不可分,因此React沒有將標記分離到不一樣的文件中,而是將它們組合到了一塊兒,這個地方就是組件(Component),JSX實際上是嵌入到JavaScript中的一種結構語法;函數

JSX的書寫規範:學習

  • JSX的頂層只能有一個根元素,因此咱們不少時候會在外層包裹一個div原生(或者使用後面咱們學習的Fragment);
  • JSX中的標籤能夠是單標籤,也能夠是雙標籤;(注意:若是是單標籤,必須以/>結尾;
  • 咱們一般在jsx的外層包裹一個小括號(),這樣能夠方便閱讀,而且jsx能夠進行換行書寫;以下例子:
return (
          <div>
            <h2>電影列表1</h2>
            <ul>
              {liArray}
            </ul>

            <h2>電影列表2</h2>
            <ul>
              {
                this.state.movies.map((item) => {
                  return <li>{item}</li>
                })
              }
            </ul>
          </div>
        )
複製代碼

1.2 JSX嵌入表達式

若是咱們jsx中的內容是動態的,咱們能夠經過表達式來獲取:ui

  • 書寫規則:{表達式}
  • 大括號內能夠是變量、字符串、數組、函數調用等任意js表達式;如上例子:

1.2.1jsx中的註釋

jsx是嵌入到JavaScript中的一種語法,因此在編寫註釋時,須要經過JSX的語法來編寫:this

<div>
  {/* 我是一段註釋 */}
  <h2>Hello World</h2>
</div>
複製代碼

1.2.2JSX嵌入變量

  • 當變量是Number、String、Array類型時,能夠直接顯示
  • 當變量是null、undefined、Boolean類型時,內容爲空;
    • 若是但願能夠顯示null、undefined、Boolean,那麼須要轉成字符串;
    • 轉換的方式有不少,好比toString方法、和空字符串拼接,String(變量)等方式;
  • 對象類型不能做爲子元素(not valid as a React child)不然會報錯
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      name: "why",
      age: 18,
      hobbies: ["籃球", "唱跳", "rap"],
      
      test1: null,
      test2: undefined,
      flag: false,

      friend: {
        name: "kobe",
        age: 40
      }
    }
  }

  render() {
    return (
      <div>
        {/* 我是一段註釋 */}
        <h2>Hello World</h2>
      </div>

      <div>
        {/* 1.能夠直接顯示 */}
        <h2>{this.state.name}</h2>
        <h2>{this.state.age}</h2>
        <h2>{this.state.hobbies}</h2>

        
        {/* 2.不顯示 */}
        <h2>{this.state.test1}</h2>
        <h2>{this.state.test1 + ""}</h2>
        <h2>{this.state.test2}</h2>
        <h2>{this.state.test2 + ""}</h2>
        <h2>{this.state.flag}</h2>
        <h2>{this.state.flag + ""}</h2>
        
        {/* 3.報錯,不顯示 */}
        <h2>123{this.state.friend}</h2>
      </div>
    )
  }
}

ReactDOM.render(<App/>, document.getElementById("app"));
複製代碼

說明:爲何null、undefined、Boolean在JSX中要顯示爲空內容呢?spa

  1. 在判斷結果爲false時,不顯示一個內容;
  2. 在判斷結果爲true時,顯示一個內容;

這個時候,咱們能夠編寫以下代碼:code

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      flag: false
    }
  }

  render() {
    return (
      <div>
        {this.state.flag ? <h2>我是標題</h2>: null}
        {this.state.flag && <h2>我是標題</h2>}
      </div>
    )
  }
}
複製代碼

1.2.3JSX嵌入表達式

JSX中,也能夠是一個表達式。

  1. 運算表達式
  2. 三元運算符
  3. 執行一個函數
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      firstName: "kobe",
      lastName: "bryant",
      age: 20
    }
  }

  render() {
    return (
      <div>
        {/* 運算表達式 */}
        <h2>{this.state.firstName + " " + this.state.lastName}</h2>
        {/* 三元運算符 */}
        <h2>{this.state.age >= 18 ? "成年人": "未成年人"}</h2>
        {/* 執行一個函數 */}
        <h2>{this.sayHello("kobe")}</h2>
      </div>
    )
  }

  sayHello(name) {
    return "Hello " + name;
  }
}
複製代碼

1.2.4 jsx綁定屬性

不少時候,描述的HTML原生會有一些屬性,而咱們但願這些屬性也是動態的:

  1. 好比元素都會有title屬性
  2. 好比img元素會有src屬性
  3. 好比a元素會有href屬性
  4. 好比元素可能須要綁定class (注意:綁定class比較特殊,由於class在js中是一個關鍵字,因此jsx中不容許直接寫class,,寫法:使用className替代)
  5. 好比原生使用內聯樣式style(style後面跟的是一個對象類型,對象中是樣式的屬性名和屬性值,注意:這裏屬性名轉成駝峯標識,而不是鏈接符- ;)

下面爲各種屬性綁定寫法

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      title: "你好啊",
      imgUrl: "https://upload.jianshu.io/users/upload_avatars/1102036/c3628b478f06.jpeg?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
      link: "https://www.baidu.com",
      active: false
    }
  }

  render() {
    return (
      <div>
        <h2 title={this.state.title}>Hello World</h2>
        <img src={this.state.imgUrl} alt=""/>
        <a href={this.state.link} target="_blank">百度一下</a>
        <div className={"message " + (this.state.active ? "active": "")}>你好啊</div>
        <div className={["message", (this.state.active ? "active": "")].join(" ")}>你好啊</div>
        <div style={{fontSize: "30px", color: "red", backgroundColor: "blue"}}>我是文本</div>
      </div>
    )
  }
}
複製代碼

1.3 jsx事件監聽

1.3.1和原生綁定區別

原生DOM原生有一個監聽事件,常規操做通常爲:

  1. 獲取DOM原生,添加監聽事件;
  2. 在HTML原生中,直接綁定onclick;
<button onclick="btnClick()">點我一下</button> //btnClick()這樣寫的緣由是onclick綁定的後面是跟上JavaScript代碼;
<script>
  function btnClick() {
  console.log("按鈕發生了點擊");
}
</script>
複製代碼

在React中是如何操做de?

React中的事件監聽,這裏主要有兩點不一樣

  1. React 事件的命名採用小駝峯式(camelCase),而不是純小寫;
  2. 咱們須要經過{}傳入一個事件處理函數,這個函數會在事件發生時被執行;
class App extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.btnClick}>點我一下(React)</button>
      </div>
    )
  }

  btnClick() {
    console.log("React按鈕點擊了一下")
  }
}
複製代碼

1.3.2this綁定問題

在事件執行後,咱們可能須要獲取當前類的對象中相關的屬性:

  • 好比咱們這裏打印:this.state.message
    • 可是這裏會報錯:Cannot read property 'state' of undefined
    • 緣由是this在這裏是undefined -若是咱們這裏直接打印this,也會發現它是一個undefined
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      message: "你好啊,李銀河"
    }
  }

  render() {
    return (
      <div>
        <button onClick={this.btnClick}>點我一下(React)</button>
      </div>
    )
  }

  btnClick() {
    console.log(this);
    console.log(this.state.message);
  }
}
複製代碼

爲何是undefined呢?

  • 緣由是btnClick函數並非咱們主動調用的,並且當button發生改變時,React內部調用了btnClick函數;
  • 而它內部調用時,並不知道要如何綁定正確的this;

如何解決this的問題呢? 方案一:bind給btnClick顯示綁定this

  • 這裏咱們主動將btnClick中的this經過bind來進行綁定(顯示綁定)
  • 那麼以後React內部調用btnClick函數時,就會有一個this,而且是咱們綁定的this;
<button onClick={this.btnClick.bind(this)}>點我一下(React)</button>
複製代碼

但若是我有兩個函數都須要用到btnClick的綁定咱們發現 bind(this) 須要書寫兩遍;:

<button onClick={this.btnClick.bind(this)}>點我一下(React)</button>
<button onClick={this.btnClick.bind(this)}>也點我一下(React)</button>
複製代碼

咱們能夠經過在構造方法中直接給this.btnClick綁定this來解決(注意查看 constructor 中咱們的操做:this.btnClick = this.btnClick.bind(this);):

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      message: "你好啊,李銀河"
    }

    this.btnClick = this.btnClick.bind(this);
  }

  render() {
    return (
      <div>
        <button onClick={this.btnClick}>點我一下(React)</button>
        <button onClick={this.btnClick}>也點我一下(React)</button>
      </div>
    )
  }

  btnClick() {
    console.log(this);
    console.log(this.state.message);
  }
}
複製代碼

方案二:使用 ES6 class fields 語法

你會發現我這裏將btnClick的定義變成了一種賦值語句:

  • 這是ES6中給類定義屬性的方法,稱之爲class fields語法;
  • 由於這裏咱們賦值時,使用了箭頭函數,因此在當前函數中的this會去上一個做用域中查找;
  • 而上一個做用域中的this就是當前的對象;
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      message: "你好啊,李銀河"
    }
  }

  render() {
    return (
      <div>
        <button onClick={this.btnClick}>點我一下(React)</button>
        <button onClick={this.btnClick}>也點我一下(React)</button>
      </div>
    )
  }

  btnClick = () => {
    console.log(this);
    console.log(this.state.message);
  }
}
複製代碼

方案三:事件監聽時傳入箭頭函數(推薦)

由於 onClick 中要求咱們傳入一個函數,那麼咱們能夠直接定義一個箭頭函數傳入:

  • 傳入的箭頭函數的函數體是咱們須要執行的代碼,咱們直接執行 this.btnClick();
  • this.btnClick()中經過this來指定會進行隱式綁定,最終this也是正確的;
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      message: "你好啊,李銀河"
    }
  }

  render() {
    return (
      <div>
        <button onClick={() => this.btnClick()}>點我一下(React)</button>
        <button onClick={() => this.btnClick()}>也點我一下(React)</button>
      </div>
    )
  }

  btnClick() {
    console.log(this);
    console.log(this.state.message);
  }
}
複製代碼

1.3.3事件參數傳遞

在執行事件函數時,有可能咱們須要獲取一些參數信息:好比event對象、其餘參數

狀況一:獲取event對象

  • 不少時候咱們須要拿到event對象來作一些事情(好比阻止默認行爲)
  • 假如咱們用不到this,那麼直接傳入函數就能夠獲取到event對象;
class App extends React.Component {
  constructor(props) {

  render() {
    return (
      <div>
        <a href="http://www.baidu.com" onClick={this.btnClick}>點我一下</a>
      </div>
    )
  }

  btnClick(e) {
    e.preventDefault();
    console.log(e);
  }
}
複製代碼

狀況二:獲取更多參數

  • 有更多參數時,咱們最好的方式就是傳入一個箭頭函數,主動執行的事件函數,而且傳入相關的其餘參數;
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      names: ["衣服", "鞋子", "褲子"]
    }
  }

  render() {
    return (
      <div>
        <a href="http://www.baidu.com" onClick={this.aClick}>點我一下</a>

        {
          this.state.names.map((item, index) => {
            return (
              <a href="#" onClick={e => this.aClick(e, item, index)}>{item}</a>
            )
          })
        }
      </div>
    )
  }

  aClick(e, item, index) {
    e.preventDefault();
    console.log(item, index);
    console.log(e);
  }
}
複製代碼

本文是經過學習codewhy的 React課程總結

相關文章
相關標籤/搜索