React基礎語法
React介紹
1.React是什麼?
- React 是由 Facebook 開源的一個JS 庫
- 官方解釋: React 是一個聲明式,高效且靈活的用於構建用户界面的 JavaScript 庫
<br/>
2.React的特點(瞭解)
聲明式編程
-
什麼是聲明式編程:
- 它描述目標的性質,讓電腦明白目標,而非流程
- 聲明式編程是告訴計算機需要計算 “什麼” 而不是 “如何” 去計算
-
前端開發模式:
- 聲明式編程是目前整個大前端開發的模式:Vue、React、Flutter、SwiftUI
- 它允許我們只需要維護自己的狀態
- 當狀態改變時,React可以根據最新的狀態去渲染我們的UI界面
組件化開發
-
組件是 React 中重要思想
- 它提供了一種抽象, 我們可以開發出一個獨立可複用的小組件來構造我們的應用
-
組件化思想應用
- 有了組件化的思想,儘可能將頁面拆分成一個個小的,可複用的組件
- 這樣讓我們代碼更方便組織和管理,並且擴展性也強
多平台適配
- 2013年,React發佈之初主要是開發Web頁面;
- 2015年,Facebook推出了ReactNative,用於開發移動端跨平台;(雖然目前Flutter非常火爆,但是還是有很多公司在使用 ReactNative);
- 2017年,Facebook推出ReactVR,用於開發虛擬現實Web應用程序;(隨着5G的普及,VR也會是一個火爆的應用場景
<br/>
3.React開發依賴
-
開發 React 必須依賴這三個庫:
react: 包含 react 所必須的核心代碼react-dom: react渲染不同平台所需要的核心代碼babel: 將 jsx 轉換成React代碼工具
-
React為什麼要依賴這三個庫:
- 其實, 這三個庫式各司其職, 目就是讓每一個庫單純做自己的事情
- 為什麼要進行拆分呢?
- react中包含了 react 和 react-native 所共同擁有的核心代碼
-
react-dom針對 web 和 native 所完成的事情不同:- web端:
react-dom會將jsx最終渲染成真實的DOM, 顯示在瀏覽器中 - native端:
react-dom會將jsx最終渲染成原生的控件 (比如Android中的Butto, iOS中的UIButton)
- web端:
<br/>
4.認識Bable
-
babel是什麼:
- 是目前前端使用非常廣泛的編譯器、轉碼器
- 可以將ES6代碼轉為ES5代碼,從而在現有環境執行
-
React和Babel的關係:- 默認情況下
React其實可以不用babel - 但前提是我們使用
React.createElement來編寫源代碼, 它編寫的代碼非常繁瑣可讀性差 - 我們就可以直接編寫jsx(JavaScript XML)的語法,並且讓babel幫助我們轉換成
React.createElement
- 默認情況下
<br/>
5.引入React依賴
-
如何添加這三個依賴:
- 方式一:直接CDN引入
- 方式二:下載後,添加本地依賴
- 方式三:通過npm管理
- 暫時我們直接通過CDN引入
<script src="https://unpkg.com/react@16/umd/react.development.js" ></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<br/>
React初體驗
1.React基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React初體驗</title>
</head>
<body>
<div id="app"></div>
<!-- 添加React的依賴 -->
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- 注意事項: 使用jsx,並且希望script中的jsx代碼被解析,必須在script標籤中添加type屬性 -->
<script type="text/babel">
// <h2></h2>: jsx代碼
ReactDOM.render(<h2>Hello World</h2>, document.getElementById('app'))
</script>
</body>
</html>
-
React.render函數- 參數一: 要渲染的內容, 可以是HTML元素, 也可以是React的組件
- 參數二: 將渲染的內容, 掛載到哪一個HTML元素上
- 我們可以通過
{}語法來引入外部的變量或者表達式
<br/>
2.React初體驗組件化開發
-
整個邏輯其實可以看做一個整體,那麼我們就可以將其封裝成一個組件:
- 我們説過
ReactDOM.render第一參數是一個HTML元素或者一個組件 - 所以我們可以先將之前的業務邏輯封裝到一個組件中,然後傳入到
ReactDOM.render函數中的第一個參數
- 我們説過
- 在
React中, 如何封裝一個組件呢? -
這裏暫時使用類的方式封裝組件:
- 定義一個類 (類名大寫, 組件的名稱是必須大寫的, 小寫會被認為是HTML元素),繼承自
React.Component -
實現當前組件的
render函數render當中返回的jsx內容,就是之後React會幫助我們渲染的內容
- 定義一個類 (類名大寫, 組件的名稱是必須大寫的, 小寫會被認為是HTML元素),繼承自
<details><summary>圖示</summary><pre><img src="https://gitee.com/xmkm/cloudPic/raw/master/img/20200819125150.png" /></pre></details>
//封裝APP組件
class App extends React.Component
render(){
return (
<div>hello</div>
}
// 渲染組件
ReactDOM.render(<App/>, document.getElementById ('app'))
<br/>
3.組件化-數據依賴
-
在組件中的數據,我們可以分成兩類:
- 參與界面更新的數據:當數據變量時,需要更新組件渲染的內容
- 不參與界面更新的數據:當數據變量時,不需要更新將組建渲染的內容
-
參與界面更新的數據,是定義在當前對象的
state屬性中- 我們通過在構造函數中:
this.state = {定義的數據} -
當我們的數據發生變化時,我們調用
this.setState來更新數據,並且通知React進行update操作- 在進行update操作時,就會重新調用render函數, 並且使用最新的數據,來渲染界面
- 我們通過在構造函數中:
<details><summary>圖示</summary><img src="https://gitee.com/xmkm/cloudPic/raw/master/img/20200819125220.png" /></details>
// 封裝APP組件
class App extends React.Component
constructor() {
super()
// 定義數據
this.state = {message: 'hello world'}
// 使用數據
render() {
return (
<div>
<h2x{this.state.message}</h2>
</div>
)}
}
<br/>
4.組件化-事件綁定
-
React中事件綁定: 在標籤中定義
on + 事件名- 例如:
<button onClick={this.changeText}>改變文本</button>
- 例如:
-
當前這個函數的this指向的是誰呢?
- 默認情況下是 undefined
- 這次因為React並不是直接渲染成真實的DOM, 我們所編寫的button只是一個語法糖, 它的本質React的Element對象
- 那麼在這裏發生監聽的時候,react給我們的函數綁定的
this,默認情況下就是一個undefined
-
我們在綁定的函數中,可能想要使用當前對象,比如執行
this.setState函數,就必須拿到當前對象的this- 我們就需要在調用函數時,給這個函數直接綁定this
<button onClick={this.changeText.bind(this)}>改變文本</button>
<br/>
React基礎語法
1.認識JSX
-
這段
element變量的聲明右側賦值的標籤語法是什麼呢?- 我們在
JS中不能給一個變量賦值為HTML元素 - 如果將
type="text/babel"去掉, 會語法報錯, 其實它是一段 jsx 的語法
- 我們在
-
JSX是什麼?
JSX是一種JavaScript的語法擴展(eXtension), 也在很多地方稱之為JavaScript XML- 它用於描述我們的UI界面,並且其完成可以和JavaScript融合在一起使用
- 它不同於Vue中的模塊語法, 你不需要專門學習模塊語法中的一些指令 (比如v-for、v-if、v-else、v-bind)
<br/>
2.React為什麼選擇JSX
-
React認為渲染邏輯本質上與其他UI邏輯存在內在耦合
- 比如UI需要綁定事件(button、a原生等等)
- 比如UI中需要展示數據狀態,在某些狀態發生改變時,又需要改變UI
- 他們之間是密不可分,所以React沒有講標記分離到不同的文件中
- 而是將它們組合到了一起,這個地方就是組件(Component)
-
JSX的書寫規範:
- JSX的頂層只能有一個根元素
- 我們通常在 jsx 的外層包裹一個小括號(),這樣可以方便閲讀
- 注意:如果是單標籤,必須以/>結尾
<br/>
3.JSX的使用
- JSX中的註釋: { / JSX中的註釋 / }
-
JSX中嵌入變量
- 情況一: 當變量是Number、 String、 Array 類型是, 可以直接顯示
-
情況二: 當變量是null、undefined、Boolean類型時,內容為空
- 如果希望顯示null、undefined、Boolean,可以轉換為字符串
- 方式有很多,比如:toString方法、和 空字符串拼接 等等
- 情況三:對象類型不能作為子元素(not valid as a React child)
- <details>
<summary>JSX嵌入表達式</summary>
<li>運算表達式</li>
<li>三元運算符</li>
<li>調用函數</li>
</details>
1.認識JSX
-
這段
element變量的聲明右側賦值的標籤語法是什麼呢?- 我們在
JS中不能給一個變量賦值為HTML元素 - 如果將
type="text/babel"去掉, 會語法報錯, 其實它是一段 jsx 的語法
- 我們在
-
JSX是什麼?
- JSX是一種JavaScript的語法擴展(eXtension), 也在很多地方稱之為JavaScript XML
- 它用於描述我們的UI界面,並且其完成可以和JavaScript融合在一起使用
- 它不同於Vue中的模塊語法, 你不需要專門學習模塊語法中的一些指令 (比如v-for、v-if、v-else、v-bind)
2.React為什麼選擇JSX
-
React認為渲染邏輯本質上與其他UI邏輯存在內在耦合
- 比如UI需要綁定事件(button、a原生等等)
- 比如UI中需要展示數據狀態,在某些狀態發生改變時,又需要改變UI
- 他們之間是密不可分,所以
React沒有將標記分離到不同的文件中 - 而是將它們組合到了一起,這個地方就是組件(Component)
-
JSX的書寫規範:JSX的頂層只能有一個根元素- 我們通常在
jsx的外層包裹一個小括號(),這樣可以方便閲讀 - 注意:如果是單標籤,必須以
/>結尾
3.JSX的使用
- JSX中的註釋: { /* JSX中的註釋 */ }
-
JSX中嵌入變量
- 情況一: 當變量是Number、 String、 Array 類型是, 可以直接顯示
-
情況二: 當變量是null、undefined、Boolean類型時,內容為空
- 如果希望顯示null、undefined、Boolean,可以轉換為字符串
- 方式有很多,比如:toString方法、和 空字符串拼接 等等
- 情況三:對象類型不能作為子元素(not valid as a React child)
-
JSX嵌入表達式
React綁定屬性
1.綁定普通屬性
- 例如:
<h2 title={title}>綁定普通屬性</h2>
2.綁定class
- 注意事項: 在JSX中使用 className 來綁定class
- 例如:
<div className="aa">使用className來綁定class</div>
3.綁定style
- 注意事項: 裏面層需要再包裹一對大括號
- 例如:
div style={{ color: 'red'}}>綁定style</div>
React事件綁定
1.React事件綁定
-
在
React中監聽事件- React 事件的命名採用小駝峯式 (camelCase),而不是純小寫
- 我們需要通過
{}傳入一個事件處理函數,這個函數會在事件發生時被執行
2.this的綁定問題
-
在事件執行後, 我們可能需要獲取當前類中對象的相關屬性, 這個時候需要用
this- 如果函數事件處理函數中打印 this , 會發現是
undefined
- 如果函數事件處理函數中打印 this , 會發現是
-
為什麼是
undefined呢?- 原因是
btnClick函數並不是我們主動調用的, 而且當button觸發點擊事件時,React內部調用了btnClick函數 - 而它內部調用時, 並不知道如何綁定正確的
this
- 原因是
-
如何解決:
- 方案一:
bind給btnClick顯示綁定this - 方案二: 使用
ES6 class fields語法 - 方案三: 事件監聽時傳入箭頭函數(推薦)
- 方案一:
3.事件參數傳遞
-
情況一: 獲取
event對象- 如果沒有傳遞參數,默認參數是:
event事件參數對象
- 如果沒有傳遞參數,默認參數是:
-
情況二: 獲取
event對象 和 更多參數- 有更多參數時,我們最好的方式就是傳入一個箭頭函數
- 主動調用事件函數,並且傳入相關的其他參數
補充兩個知識點
- 一: 箭頭函數永遠不會綁定this
-
即使使用
call或apply綁定this了 ,箭頭函數綁定的this不會生效- 箭頭函數中
this依然是: 最近作用域中的this
- 箭頭函數中
-
二: bind綁定的 this 優先級比 apply 或 call 要高
- 即使是後面通過
apply或call綁定this也不會生效, 依然是bind綁定的this
- 即使是後面通過
React條件渲染
1.React條件渲染
某些情況下,界面的內容會根據不同的情況顯示不同的內容,或者決定是否渲染某部分內容在Vue中, 我們通過指令來控制比如: v-if、v-show
在React中,所有條件判斷都和普通的
JavaScript代碼一致
-
方式一:條件判斷語法
- 適合邏輯多的情況
-
方式二:三元運算符
- 適合邏輯比較簡單
-
邏輯與: 運算符&&
- 適合如果條件成立,渲染某一個組件;如果條件不成立,什麼內容也不渲染;
-
v-show的效果
- 主要是控制
display屬性是否為none
- 主要是控制
2.React列表渲染
- 真實開發中我們會從服務器請求到大量的數據,數據會以列表的形式存儲
- 在React中,展示列表最多的方式就是使用數組的
map高階函數 -
很多時候我們在展示一個數組中的數據之前,需要先對它進行一些處理
- 比如過濾掉一些內容:filter函數
- 比如截取數組中的一部分內容:slice函數
3.列表中的key
- 我們會發現在前面的代碼中只要展示列表都會警告:
- 這個警告是告訴我們需要在列表展示的jsx中添加一個key.
- 至於如何添加一個
key,為什麼要添加一個key,這個我們放到後面講解setState時再來討論
JSX的本質
1.JSX的本質
-
JSX僅僅只是React.creteElement(component, pops, ...children)函數的語法糖- 所有的 JSX 代碼最終被轉換成 React.createElement的函數調用
-
createElement需要傳遞三個參數:-
參數一:
type- 當前 ReactElement 的類型
- 如果是標籤元素, 那麼就使用字符串表示"diy"
- 如果是組件元素, 那麼就直接使用組件的名稱
-
參數二:
config- 所有
jsx中的屬性都在 config 中以對象的屬性和值的形式存儲
- 所有
-
參數三:
children- 存放在標籤中的內容, 以 children 數組的方式進行存儲
-
// jsx -> babel -> React.createElement()
// JSX最終會轉換成 React.createElement(type, config, children)
const message = React.createElement("h2", null, "hello world")
ReactDOM.render(message, document.getElementById("app"))
2.Babel官網查看
- 我們知道默認的 JSX 是通過 babel 幫我們進行語法轉換的, 所以我們之前寫的 JSX 代碼都需要依賴 babel
- 我們可以在bebel官網查看: JSX 轉換成 React.creteElement 過程
下拉查看
Virtual DOM
1.虛擬DOM的創建過程
- 我們通過
React.createElement最終創建出來一個ReactElement對象 -
這個
ReactElement對象是什麼作用呢?React為什麼要創建它呢?- 原因是
React利用ReactElement對象組成了一個JavaScript的對象樹 - JavaScript的對象樹就是虛擬DOM (Virtual DOM)
- 原因是
- 而
ReactElement最終形成的樹結構就是 Virtual DOM
2.JSX->VirtualDom->DOM
3.聲明式編程
- 虛擬DOM幫助我們從命令式編程轉到了聲明式編程的模式
-
React官方的説法: Virtual DOM 是一種編程理念
- 在這個理念中,UI以一種理想化或者説虛擬化的方式保存在內存中,並且它是一個相對簡單的JavaScript對象
- 我們可以通過 ReactDOM.render 讓 虛擬DOM 和 真實DOM同步起來,這個過程中叫做協調(Reconciliation)
-
這種編程的方式賦予了React聲明式的API:
- 你只需要告訴React希望讓UI是什麼狀態
- React來確保DOM和這些狀態是匹配的
- 你不需要直接進行DOM操作,只可以從手動更改DOM、屬性操作、事件處理中解放出來