前端學習筆記(十六) --React 學習-2

今天(指兩天)繼續學習 React。html

1. 事件

1.1 JSX 屬性寫法

//普通 html:
<button onclick="printMe()"></button>

// JSX
<button onClick={printMe()}></button>複製代碼

能夠看到:①onclick成爲了onClick。②函數不能用引號react

1.2 添加事件

在 React 中,一般是在元素初始化的時候添加監聽器,而不是用 addEventListener,由於操做的基本都是 React 元素而不是 DOM 元素。數組

// function 組件
function Button(props){
  function handleClick(e){
    e.target.style.color = "red";
  }
  
  return  (<button onClick={handleClick}>A button</button>);
}複製代碼

class 組件須要注意 this 的指向,由於在 onClick={handleClick} 中,handleClick 是回調函數,回調函數的 this 是指向 window 的,這是 JS 的默認行爲。所以須要在構造函數中對 handleClick 進行綁定處理(這沒有問題,由於原型方法比構造函數更早)。瀏覽器

// class 組件
class Button extends React.Component {
  constructor(props){
    super(props);
    this.handleClick = this.handleClick.bind(this); // 給 handleClick 綁定 this
                                                    // 由於該函數以後會被用做回調函數
  }
  handleClick() {
    console.log(this);
  }
  render() {
    return (
      <button onClick={ this.handleClick }> // 回調函數
        A button
      </button>
    );
  }
}複製代碼

1.3 給事件添加參數

給事件處理函數添加參數有兩種方法,箭頭函數或者 bind。ide

<button onClick={ (e) => this.handleClick(id, e, oid) }>A button</button>
<button onClick={ this.handleClick.bind(this, id, oid) }>A button</button>複製代碼

區別在於事件對象的傳入(皆以上面代碼的參數傳入順序爲例):函數

  • 第一種方式,e 在傳入的時候在什麼位置,handleClick 時就在什麼位置。
  • 第二種方式,e 做爲最後一個參數被傳入。

2. 條件渲染

條件渲染並非新的語法,只是一種使用方式。好比說建立三個組件,UserGreeting, GuestGreeting, Greeting。其中 Greeting 根據登陸狀態返回剩餘兩個組件中的一個。學習

2.1 元素變量

把一些元素存進變量,以後再用大括號組合進其餘元素,因爲變量能夠根據條件改變,渲染也會改變,以下圖(LoginButton 和 LogoutButton 事先已建立)。this

2.2 與運算符 &&

上面在大括號裏嵌入存儲了元素的變量。其實因爲大括號裏能夠嵌入表達式,還有不少種方式來寫。好比與運算符 &&。3d

return ( { isLogin && <LogoutButton />} );複製代碼

isLogin 爲 false 的時候,後面的部分不會運行。老技巧了。component

2.3 三元運算符

沒什麼好說的。上面的例子能夠改寫成這樣。

簡化了許多。

2.4 null 表示不渲染

若是在 render 裏返回 null,則組件不會被渲染。
可是組件的生命週期不受影響會照常進行。

3. 列表 & Key

3.1 列表

表達式能夠解析列表。

  1. 普通列表:
  2. 列表裏有元素:

3.2 key

若是運行上述第二個代碼,控制檯會有報錯提示每個列表元素必須有 key 屬性,以下:

  • 在控制檯上是找不到這個屬性的,這是用於輔助 React 來識別元素的修改的,所以每一個 key 須要在這個列表中是獨一無二的字符串。
  • 若是不定義 key,會默認使用元素的索引創建 key,可是不建議這樣作,會有不少問題。好比說元素順序修改了。

3.3 key 定義的地方

key 只有放在數組上下文附近纔有意義。這個很差描述,具體見文章

3.4 key 的使用

key 只能被 React 自身使用,無法訪問。若是想要使用 key 的值,只能在傳值給 key 的時候,傳給一個別的屬性,再去訪問那個屬性。

4. 表單

4.1 受控組件

受控組件指的是受代碼控制而不是用戶控制的組件。
一個普通的表單元素,會受到用戶控制,每當用戶輸入的時候,表單的 value 就會更改。
要想接受用戶的輸入,就要使用組件的 state,例如:

  • 可是這樣的問題在於,這只是作了一次初始化,生成一個輸入框,初始值爲 state 的初始值。
  • 而且此時若是在瀏覽器中打開會發現,輸入框變成只讀了,永遠顯示初始值,不能被更改。
  • 這樣的結果是能夠預測的,由於輸入框的值是 this.state.name,用戶輸入的時候並不會更改這個值,因此顯示的結果也就只會是初始值不變。
  • 雖然這不是咱們想要的,可是能夠看出此時輸入框的值已經徹底受代碼控制而不是用戶控制了,所以被稱做受控組件。

4.1.1 控制值-input[type="text"]

爲了控制填入的值,須要使用 onChange,每次輸入框用戶改變值的時候,都會更新 state:

  • e 事件被傳入是能夠預測的,由於 onChange 是 React 的語法,其背後仍是 js 的 onchange 函數,以上寫法其實至關於:

      const btn = document.querySelector("input[type='input']");
      btn.onchange = (e) => {};複製代碼

    事件函數原本就會有 e 傳入,很合理。

4.1.2 textarea

原始的 textarea 的值並非 value 屬性而是標籤內部內容,可是 React 將其改成 value 屬性,所以用法徹底和 input 同樣。

4.1.3 單選/多選 select

寫法以下:須要注意的幾點以下:

  1. 一旦被受控,selected 就沒有意義
  2. 若是要選多個值,則 value 爲數組。
    1. 直接寫 multiple 也行,若是要寫 true,就必須加大括號
    2. handleChange 不能用 e.target.value,這個只有一個值,選擇了多個返回的是 selectedOptions。不過這個屬性 IE 不支持,若是要支持,參考這裏的回答

4.1.4 文件輸入 input[type="file"]

文件輸入只能被用戶控制,只能爲非受控組件。

4.1.5 處理多個輸入

這裏指的不是 multiple select 那種。而是處理多個輸入標籤,如:

處理方式是加上 name 屬性,handleChange 的時候根據 name 判斷更改哪一個框的值。

  • 注意 checkbox 的輸入值爲 e.target.checked。(radio 也是)

4.1.6 value 的可編輯性

通常來講,若是設置了 value 的值,則輸入框會變成只讀。但有時候設置了 value(而且沒有設置 handleChange),但仍然能夠編輯,那說明 value 的值爲 null 和 undefined。(好比說使用某個變量的值,而後這個變量由於某種狀況變成了 undefined 或者 null。)

  • value 固定爲 11

  • value 爲 null

4.2 非受控組件

從上面能夠看出,每一種輸入類型都要爲之寫專門的輸入處理,這很麻煩。有時候只須要簡單的輸入而後提交,不須要作複雜的判斷(好比實時判斷),只須要正在提交的時候是正確的值便可。那麼此時能夠用非受控組件。

因爲非受控組件須要使用 ref,放在以後學習。不過有一張表顯示二者之間的區別,助你決定使用哪一個:

  • 上圖出處爲這篇文章,區別介紹的更加詳細。

4.3 成熟的表單提交解決方案

官方文檔推薦了 Formik,用於輕鬆管理複雜的表單驗證。

5. 狀態提高

狀態提高用於多個組件共享相同的變化數據。
這裏仍是參考文檔來看比較好。

一些坑和心得:

  • render 中使用 if...else... 判斷時,即便 if...else...囊括了全部狀況,編譯器也不讓經過。要用三目運算符
  • 狀態提高用的仍是自上而下的數據流。數據從父組件流向子組件。
  • 整個例子的流程就像是:

6. 組合

6.1 props.children

props.children 是一個特殊命名的屬性:這裏使用組件的方式再也不是 <Panel />,而是使用開放和閉合標籤包裹了一段 html 內容。這段內容將會做爲 props.children 傳給子組件。

6.2 傳遞自定義元素

props.children 是特殊屬性,傳的是整個 innerHTML。若是想傳一些自定義的元素的話。能夠直接以相似:<MyComponent myDefined={<h1>this is a title</h1>}> 的方式傳遞,props 並不對值的類型有要求。JSX 語法自己也只是元素。

6.3 組合

能夠經過以上語法 「組合」 成新的組件。

相關文章
相關標籤/搜索