天天看點

React 基本文法入門一 React簡介二 React 基本文法Hello, World

文章目錄

  • 一 React簡介
    • 1.1 介紹
    • 1.2 特點
    • 1.3 插件安裝
    • 1.4 學習概述
  • 二 React 基本文法
    • 2.1 Hello World
    • 2.2 React 元素渲染
      • 2.2.1 元素渲染
      • 2.2.2 虛拟Demo與Diff算法
    • 2.3 JSX文法
    • 2.4 元件與子產品的了解
    • 2.4 元件
      • 2.4.1函數式元件
      • 2.4.2類元件
    • 2.5 元件的核心屬性
      • 2.5.1 核心元件執行個體:State
        • 2.5.1.1 什麼是State?
        • 2.5.1.2 初始化state?
        • 2.5.1.3 更新state?
        • 2.5.1.4 元件的state?
        • 2.5.1.5 案例
        • 2.5.1.6 簡化
        • 2.5.1.7 擴充
      • 2.5.2 核心元件執行個體:Props
        • 2.5.2.1 簡單入門
        • 2.5.2.2 什麼是props
        • 2.5.2.3 類型檢查
        • 2.5.2.4 函數式元件props
        • 2.5.2.5 總結
      • 2.5.3 核心元件執行個體:Ref
        • 2.5.3.1 方法一:傳入字元串(不推薦使用)
        • 2.5.3.2 方法二:回調函數
        • 2.5.3.3 方法三:creatRef
      • 2.5.4 事件總結
      • 2.5.5 受控元件與非受控元件
    • 2.6 生命周期
      • 2.6.1 案例引入
      • 2.6.2 生命周期(舊 16)
        • 2.6.2.1 初始化階段
        • 2.6.2.2 更新階段
      • 2.6.3 生命周期(新 17)
        • 2.6.3.1 getDerivedStateFromProps(nextProps, prevState)
        • 2.6.3.2 getSnapshotBeforeUpdate(prevProps, prevState)(更新)

參考視訊:https://www.bilibili.com/video/BV1wy4y1D7JT

官方文檔:https://react.docschina.org/

UI元件庫:https://pro.ant.design/zh-CN/docs/overview/

參考部落格:https://juejin.cn/post/7085542534943883301

備注:我之前學習過Angualr架構,有一點的學習基礎

一 React簡介

1.1 介紹

React 是一個用于建構使用者界面的 JAVASCRIPT 庫。主要用于建構UI,很多人認為 React 是 MVC 中的 V(視圖)。React 起源于 Facebook 的内部項目,用來架設 Instagram 的網站,并于 2013 年 5 月開源。React 擁有較高的性能,代碼邏輯非常簡單,越來越多的人已開始關注和使用它。

1.2 特點

聲明式

React 使建立互動式 UI 變得輕而易舉。為你應用的每一個狀态設計簡潔的視圖,當資料變動時 React 能高效更新并渲染合适的元件。以聲明式編寫 UI,可以讓你的代碼更加可靠,且友善調試

元件化

建構管理自身狀态的封裝元件,然後對其組合以構成複雜的 UI。由于元件邏輯使用 JavaScript 編寫而非模闆,是以你可以輕松地在應用中傳遞資料,并保持狀态與 DOM 分離。

一次學習,随處編寫

無論你現在使用什麼技術棧,在無需重寫現有代碼的前提下,通過引入 React 來開發新功能。

React 還可以使用 Node 進行伺服器渲染,或使用 React Native 開發原生移動應用。

1.3 插件安裝

React 基本文法入門一 React簡介二 React 基本文法Hello, World
React 基本文法入門一 React簡介二 React 基本文法Hello, World

1.4 學習概述

React 基本文法入門一 React簡介二 React 基本文法Hello, World

二 React 基本文法

2.1 Hello World

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<!-- 注意導入時依賴的順序 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>

<div id="example">
	
</div>

<!-- react表達式 -->
<script type="text/babel">
// 虛拟元素渲染
ReactDOM.render(
	<h1>Hello, world!</h1>,
	// 元素根節點
	document.getElementById('example')
);
</script>

</body>
</html>
           

這樣我們将得到第一個React頁面,效果如下

React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.2 React 元素渲染

2.2.1 元素渲染

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<!-- 注意導入時依賴的順序 -->
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<!--   demo容器 -->
<div id="example">
</div>
<!-- react表達式 -->
<script type="text/babel">
// 虛拟元素渲染
ReactDOM.render(
	<h1>Hello, world!</h1>,
	// 元素根節點
	document.getElementById('example')
);
</script>

</body>
</html>
           
  • 元素是構成 React 應用的最小機關,它用于描述螢幕上輸出的内容。
const element = <h1>Hello, world!</h1>;
           
  • 在此 div 中的所有内容都将由 React DOM 來管理,是以我們将其稱為 “根” DOM 節點。

我們用 React 開發應用時一般隻會定義一個根節點。但如果你是在一個已有的項目當中引入 React 的話,你可能會需要在不同的部分單獨定義 React 根節點,要将React元素渲染到根DOM節點中,我們通過把它們都傳遞給 ReactDOM.render() 的方法來将其渲染到頁面上

// 虛拟元素渲染
ReactDOM.render(
	<h1>Hello, world!</h1>,
	// 元素根節點
	document.getElementById('example')
);
           

2.2.2 虛拟Demo與Diff算法

虛拟Demo

  • 當我們更新了state中的值的時候,React會去調用render()方法來重新渲染整個元件的UI,但是如果我們真的去操作這麼大量的DOM,顯然性能是堪憂的。
  • React實作了一個Virtual DOM,元件的真實DOM結構和Virtual DOM之間有一個映射的關系,React在虛拟DOM上實作了一個diff算法,當render()去重新渲染元件的時候,diff會找到需要變更的DOM,然後再把修改更新到浏覽器上面的真實DOM上,是以,React并不是渲染了整個DOM樹,Virtual DOM就是JS資料結構,是以比原生的DOM快得多。

Diff算法

  • React的 virtual dom的性能好也離不開它本身特殊的diff算法。傳統的diff算法時間複雜度達到o(n3),而react的diff算法時間複雜度隻是o(n),react的diff能減少到o(n)依靠的是react diff的三大政策。
  • 政策一(tree diff):Web UI中DOM節點跨層級的移動操作特别少,可以忽略不計。(DOM結構發生改變-----直接解除安裝并重新creat)
  • 政策二(component diff):DOM結構一樣-----不會解除安裝,但是會update
  • 政策三(element diff):所有同一層級的子節點.他們都可以通過key來區分-----同時遵循1.2兩點

具體知識請參考:https://blog.csdn.net/qq_36407875/article/details/84965311

2.3 JSX文法

React 使用 JSX 來替代正常的 JavaScript,JSX 是一個看起來很像 XML 的 JavaScript 文法擴充。

JSX, 一種 JavaScript 的文法擴充。 我們推薦在 React 中使用 JSX 來描述使用者界面。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>JSX</title>
		<!-- 注意導入時依賴的順序 -->
		<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
		<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
		<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
	</head>
	<body>

		<!-- 容器 -->
		<div id="root">
		</div>
    
		<!-- react表達式 -->
		<script type="text/babel">
			const VDEMO=(
			<h2 id="test">
			<span>測試,練習</span>
			</h2>
			)
			ReactDOM.render(VDEMO,// 元素根節點
			document.getElementById('root'));
		</script>

	</body>
</html>

           
  • 規則一:定義虛拟Demo時,不要寫引号。
  • 規則二:标簽中混入JS表達式時要用{}
<!-- react表達式 -->
		<script type="text/babel">
			const myid="test";
			const data="測試,練習";
			const VDEMO=(
			<h2 id="{myid}">
			<span>{data}</span>
			</h2>
			)
			// 渲染虛拟Demo
			ReactDOM.render(VDEMO,// 元素根節點
			document.getElementById('root'));
		</script>
           
  • 規則三:樣式的類名指定不要用class,要用className
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>JSX</title>
		<!-- 注意導入時依賴的順序 -->
		<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
		<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
		<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
		<style>
			.title {
				background-color: aqua;
				width: 200px;
			}
		</style>
	</head>
	<body>

		<!-- 容器 -->
		<div id="root">
		</div>

		<!-- react表達式 -->
		<script type="text/babel">
			const myid="test";
			const data="測試,練習";
			const VDEMO=(
			<h2 className="title" id="{myid}">
			<span>{data}</span>
			</h2>
			)
			// 渲染虛拟Demo
			ReactDOM.render(VDEMO,// 元素根節點
			document.getElementById('root'));
		</script>

	</body>
</html>

           

規則四:内聯樣式。要用style={{key:value}}

<!-- react表達式 -->
		<script type="text/babel">
			const myid="test";
			const data="測試,練習";
			const VDEMO=(
			<h2 className="title" id="{myid}">
			<span style={{color:'red'}}>{data}</span>
			</h2>
			)
			// 渲染虛拟Demo
			ReactDOM.render(VDEMO,// 元素根節點
			document.getElementById('root'));
		</script>
           

規則五:虛拟Demo隻有一個根标簽

<!-- react表達式 -->
		<script type="text/babel">
			const myid="test";
			const data="測試,練習";
			const VDEMO=(
			<div>
			<h2 className="title" id="{myid}">
			<span style={{color:'red'}}>{data}</span>
			</h2>
			<h2 className="title" id="{myid+1}">
			<span style={{color:'red'}}>{data}</span>
			</h2>
			</div>
			)
			// 渲染虛拟Demo
			ReactDOM.render(VDEMO,// 元素根節點
			document.getElementById('root'));
		</script>

           

規則六:标簽必須閉合

規則七:如果小寫字母開頭,就将标簽轉化為html同名元素,如果html中無該标簽對應的元素,就報錯;如果是大寫字母開頭,react就去渲染對應的元件,如果沒有就報錯

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .sss{
            color: red;
        }
    </style>
</head>
<body>
    <!-- 準備好容器 -->
    <div id="test">
        
    </div>
</body>
<!-- 引入依賴 ,引入的時候,必須就按照這個步驟-->
<script src="../js/react.development.js" type="text/javascript"></script>
<script src="../js/react-dom.development.js" type="text/javascript"></script>

<script src="../js/babel.min.js"></script>
<!--這裡使用了js來建立虛拟DOM-->
<script type="text/babel">
        const MyId = "title";
        const MyData = "Cyk";
        // 1.建立虛拟DOM
        const VDOM = (
            <h1 id = {MyId.toLocaleUpperCase()}>
                <span className = "sss" style = {{fontSize:'50px'}}>sss</span>
            </h1>
        )
        // 2.渲染,如果有多個渲染同一個容器,後面的會将前面的覆寫掉
        ReactDOM.render(VDOM,document.getElementById("test"));
</script>

</html>
           
  • 如何區分JS表達式與JS語句

表達式:會有傳回值

語句:不會有傳回值 if,switch等等

2.4 元件與子產品的了解

子產品

向外提供特定功能的js檔案,可以簡化js的編寫,達到複用,提高運作效率

元件

為了實作一個功能代碼的資源合集,可以簡化開發,代碼複用

子產品化

當應用的js都以子產品來編寫,這個應用就是子產品化的應用,簡單了解,子產品的內建

元件化

當應用一元件的方式來實作,這個應用就是元件化的展現,簡單了解。對元件的內建

2.4 元件

React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.4.1函數式元件

注意點:

  • 元件名稱必須大寫,React 會将以小寫字母開頭的元件視為原生 DOM 标簽。
  • 注意标簽的閉合,比如
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>Hello React!</title>
		<!-- 注意導入時依賴的順序 -->
		<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
		<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
		<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
	</head>
	<body>

		<div id="example">

		</div>

		<!-- react表達式 -->
		<script type="text/babel">

			// 定義函數式元件
	function MyCompent(){
		return <h1>Hello, World</h1>;
	}
	
	
// 虛拟元素渲染
ReactDOM.render(<MyCompent/>,document.getElementById('example')
);
</script>

	</body>
</html>

           
React 基本文法入門一 React簡介二 React 基本文法Hello, World

過程

  1. 我們調用 ReactDOM.render() 函數,并傳入 作為參數。
  2. React 調用 MyCompent 元件。
  3. MyCompent 元件将

    Hello, World

    元素作為傳回值。
  4. React DOM 将 DOM 高效地更新為 Hello, World。

2.4.2類元件

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>Hello React!</title>
		<!-- 注意導入時依賴的順序 -->
		<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
		<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
		<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
	</head>
	<body>

		<div id="example">

		</div>

		<!-- react表達式 -->
		<script type="text/babel">
			
	// 定義類元件
	class Mycompent extends React.Component{
		render(){
			return <h1>Hello, World 我是類元件</h1>;
		}
	}

      
// 虛拟元素渲染
ReactDOM.render(<Mycompent/>,document.getElementById('example')
);


</script>

	</body>
</html>

           
React 基本文法入門一 React簡介二 React 基本文法Hello, World

過程

  • React解析元件标簽,找到相應的元件。
  • 發現元件是類定義的,随後new出來的類的執行個體,并通過該執行個體調用到原型上的render方法。
  • 将render傳回的虛拟DOM轉化為真實的DOM,随後呈現在頁面中。

2.5 元件的核心屬性

React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.5.1 核心元件執行個體:State

2.5.1.1 什麼是State?

  • React 把元件看成是一個狀态機(State Machines)。通過與使用者的互動,實作不同狀态,然後渲染 UI,讓使用者界面和資料保持一緻。
  • React 裡,隻需更新元件的 state,然後根據新的 state 重新渲染使用者界面(不要操作 DOM)。
  • State是元件對象最重要的屬性,值是對象(可以包含多個key-value的組合)

2.5.1.2 初始化state?

對于state的使用方法,在ES5中和Es6中使用是不一樣的,我們以ES6為例,在元件的構方法中如下設定即可,設定一個預設的state屬性。

constructor(props) {
  super(props);
  this.state={
    key:value,
    ...
      }
}
           

2.5.1.3 更新state?

正确寫法

this.setState({
     key:value
 }) ;
           

錯誤寫法

注意:setState()是異步的,也就是你調用了setState()之後,React就開始準備去更新了,中間計算會可能會有一定的延時。

this.setState(),該方法接收兩種參數:對象或函數。

  1. 對象:即想要修改的state
this.setState({
     key:value
 }) ;
           
  1. 函數:接收兩個函數,第一個函數接受兩個參數,第一個是目前state,第二個是目前props,該函數傳回一個對象,和直接傳遞對象參數是一樣的,就是要修改的state;第二個函數參數是state改變後觸發的回調
正确的例子
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}))
           

2.5.1.4 元件的state?

應該說大部分的元件根據props來取得資料并渲染,但是使用者輸入,請求伺服器,操作資料庫等情況下就需要state了.官方的建議是盡量建構無狀态的元件,是為了提高性能,減少渲染次數,做法就是建構幾個無狀态的元件,在這之上建構一個有狀态和使用者和服務互動 ,然後通過props來傳遞給無狀态的元件。

元件使用state注意點

  • 不要直接的修改state
  • 狀态更新是異步的
this.setState({
  counter: this.state.counter + this.props.increment,
});
           
  • state的更新是合并後的
constructor(props) {
    super(props);
    this.state = {
      posts: [],
      comments: []
    };
  }
           

2.5.1.5 案例

需求:頁面顯示【今天天氣很炎熱】,滑鼠點選文字的時候,頁面更改為【今天天氣很涼爽】

  • 第一步頁面建構
<!--
 * @Description: state的初步使用
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-03 22:19:32
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 09:51:34
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      // 定義類元件
      class Mycompent extends React.Component {
        // 渲染
        render() {
          console.log(this);
          return (
            <h1 >
              今天天氣很涼爽
            </h1>
          );
        }
      }
      // 虛拟元素渲染
      ReactDOM.render(<Mycompent />, document.getElementById("example"));
    </script>
  </body>
</html>

           

我們可以看到我們定義的類元件實際上繼承了react的元件功能,擁有了部分屬性

React 基本文法入門一 React簡介二 React 基本文法Hello, World
  • 第二步增加類的屬性,當然根據類的相關知識,我們知道,可以根據類的構造器,來增加類的屬性
<!--
 * @Description: state的初步使用
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-03 22:19:32
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 10:12:26
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      // 定義類元件
      class Mycompent extends React.Component {
        // 構造器
        constructor(props) {
          super(props);
          // 元件的state
          this.state = { isHot: true };
         
        }
        // 渲染
        render() {
          console.log(this);
          return (
            <h1 >
              今天天氣很涼爽
            </h1>
          );
        }
        
      }
      // 虛拟元素渲染
      ReactDOM.render(<Mycompent />, document.getElementById("example"));
    </script>
  </body>
</html>

           
React 基本文法入門一 React簡介二 React 基本文法Hello, World

注意點:

  • 元件的構造函數,必須要傳遞一個props參數,後面我們會講
  • 第三步,點選事件, 修改的state的狀态,完成狀态的切換,重新渲染DEMO
<!--
 * @Description: state的初步使用
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-03 22:19:32
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 10:15:15
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      // 定義類元件
      class Mycompent extends React.Component {
        // 構造器
        constructor(props) {
          super(props);
          // 元件的state
          this.state = { isHot: true };
          // 轉換成執行個體的方法
          this.changeStatus = this.changeStatus.bind(this);
        }
        // 渲染
        render() {
          console.log(this);
          return (
            <h1 onClick={this.changeStatus}>
              今天天氣很{this.state.isHot ? "炎熱" : "涼爽"}
            </h1>
          );
        }
        // 調用方法
        changeStatus() {
          console.log("調用方法!!");
          this.setState({ isHot: !this.state.isHot });
        }
      }
      // 虛拟元素渲染
      ReactDOM.render(<Mycompent />, document.getElementById("example"));
    </script>
  </body>
</html>

           
React 基本文法入門一 React簡介二 React 基本文法Hello, World

注意點:

  • 特别關注this【重點】,類中所有的方法局部都開啟了嚴格模式,如果直接進行調用,this就是undefined,解決這個問題;

1:使用bind()方法,将方法作為執行個體的方法

// 轉換成執行個體的方法
          this.changeStatus = this.changeStatus.bind(this);
           

2:箭頭函數的寫法,會向外找到this執行個體

// 調用方法
        changeStatus=()=> {
          console.log("調用方法!!");
          this.setState({ isHot: !this.state.isHot });
        }
           
  • 綁定事件是onClick注意是指派,而不是直接調用它
  • 想要改變state,需要使用setState進行修改,如果隻是修改state的部分屬性,則不會影響其他的屬性,這個隻是合并并不是覆寫。

2.5.1.6 簡化

<!--
 * @Description: state的初步使用
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-03 22:19:32
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 10:29:22
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      // 定義類元件
      class Mycompent extends React.Component {
      	// 類的附加屬性
        state = { isHot: true };
        // 渲染
        render() {
          console.log(this);
          return (
            <h1 onClick={this.changeStatus}>
              今天天氣很{this.state.isHot ? "炎熱" : "涼爽"}
            </h1>
          );
        }
        // 調用方法,會向外尋址this的指向
        changeStatus=()=> {
          console.log("調用方法!!");
          this.setState({ isHot: !this.state.isHot });
        }
      }
      // 虛拟元素渲染
      ReactDOM.render(<Mycompent />, document.getElementById("example"));
    </script>
  </body>
</html>

           
React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.5.1.7 擴充

setState的異步更新和同步更新?

  • React控制之外的事件中調用setState是同步更新的。比如原生js綁定的事件,setTimeout/setInterval等。
  • 大部分開發中用到的都是React封裝的事件,比如onChange、onClick、onTouchMove等,這些事件處理程式中的setState都是異步處理的。

React怎麼調用同步或者異步的呢?

  • 在 React 的 setState 函數實作中,會根據一個變量 isBatchingUpdates 判斷是直接更新 this.state 還是放到隊列中延時更新,而 isBatchingUpdates 預設是 false,表示 setState 會同步更新 this.state;但是,有一個函數 batchedUpdates,該函數會把 isBatchingUpdates 修改為 true,而當 React 在調用事件處理函數之前就會先調用這個 batchedUpdates将isBatchingUpdates修改為true,這樣由 React 控制的事件處理過程 setState 不會同步更新 this.state。
  • 如果是同步更新,每一個setState對調用一個render,并且如果多次調用setState會以最後調用的為準,前面的将會廢棄;如果是異步更新,多個setSate會統一調用一次render

參考部落格:https://github.com/xzlaptt/React

2.5.2 核心元件執行個體:Props

我們想要在元件之間進行傳值,那麼props屬性就起到了這個作用,在React中props和state是兩個非常非常非常重要的屬性一定要掌握這兩個。

2.5.2.1 簡單入門

<!--
 * @Description:props基本使用
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-05 13:31:52
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 14:39:40
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="example"></div>

    <!-- react表達式 -->
    <script type="text/babel">
      // 定義類元件
      class Mycompent extends React.Component {
        render() {
          console.log(this);
          return(
          <ul>
            <li>姓名:{this.props.name}</li>
            <li>性别:{this.props.sex}</li>
            <li>年齡:{this.props.age}</li>
          </ul>);
        }
      }
      const p = { name: "小數", sex: "男", age: "10" };
      // 虛拟元素渲染
      ReactDOM.render(<Mycompent {...p}/>, document.getElementById("example"));
    </script>
  </body>
</html>

           
React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.5.2.2 什麼是props

就是你在使用一個元件的時候希望這個元件可以複用,希望他裡面的形态、所需的資料可以在我們調用的時候可以動态的傳進去。

哪兒來的props屬性

我們元件使用類建立的時候你需要繼承 React.component,這個 props 就是繼承React 來的

React 基本文法入門一 React簡介二 React 基本文法Hello, World
React 基本文法入門一 React簡介二 React 基本文法Hello, World

傳遞屬性

<元件名 屬性名=值 屬性名2=值2 .. />
propName="字元"  propName={js資料類型}
           
React 基本文法入門一 React簡介二 React 基本文法Hello, World

注意點:

  • 調用元件名的時候可以傳遞一個或多個屬性
  • 他的值雙引号就是字元串
  • 單花括号就是 jsx 的表達式
  • 表達式就是一個對象後面掉一個 api() 就是一個表達式,聲明一個變量就是語句了,調用一個變量就是表達式了

使用屬性

注意點:

  • this 代表的是元件本身(将來的執行個體),在類裡面使用 this 它指向的是元件本身

上圖中我們看到 元件本身是有 props 的 ,就然 this代表元件本身,那我們就可以通,this.props.xxx來擷取我們想要的資訊

  • 對象無法直接通過{對象}展示,在 react 在 react-dom 渲染時,資料裡面的對象拉出來不可以之間加載,要精确到裡面的鍵才可以

2.5.2.3 類型檢查

  • 如果别人在調用我們的元件的時候亂傳不同的資料會導緻我們資料可能無法産生預期效果
  • 這時就需要借助第三方類型檢查庫
  • 需要下載下傳 yarn add prop-types -save /或者/ npm install prop-types -save
  • react 元件就是一個類,類上面就有靜态屬性 defaultProps 和 propTypes
  • 正常情況下 props 的擁有權不屬于目前元件,是别人傳給你的,你用的時候用 props 來引用,是以修改的權限應該由上面來決定

寫法

Input.defaultProps = {
  value:'',
  onChange:()=>{},
  name:''
};

Input.propTypes={
  value: propsTypes.string,
  name: propsTypes.string,
  onChange: propsTypes.func
};

           

案例

<!--
 * @Description:props基本使用
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-05 13:31:52
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 15:41:43
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
    <script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      // 定義類元件
      class Mycompent extends React.Component {
        render() {
          console.log(this);
          return (
            <ul>
              <li>姓名:{this.props.name}</li>
              <li>性别:{this.props.sex}</li>
              <li>年齡:{this.props.age}</li>
            </ul>
          );
        }
      }

      // 類型檢查
      Mycompent.propTypes = {
        // 限制為字元串,且必須要
        name: PropTypes.string.isRequired,
        sex: PropTypes.string,
        age: PropTypes.number,
        // 傳遞方法
        say: PropTypes.func,
      };

      // 指定标簽預設值
      Mycompent.defaultProps = {
        sex: "女",
        age: 20,
      };

      const p = { name: "小數", sex: "男"  };
      // 虛拟元素渲染
      ReactDOM.render(<Mycompent {...p}{...say} />, document.getElementById("example"));
      
      // 傳遞方法
      function say(){
        console.log("調用方法了")
      }
    </script>
  </body>
</html>

           

簡寫

<!--
 * @Description:props基本使用
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-05 13:31:52
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 15:49:44
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
    <script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      // 定義類元件
      class Mycompent extends React.Component {
        // 類型檢查
        static propTypes = {
          // 限制為字元串,且必須要
          name: PropTypes.string.isRequired,
          sex: PropTypes.string,
          age: PropTypes.number,
          // 傳遞方法
          say: PropTypes.func,
        };
        // 指定标簽預設值
        static defaultProps = {
          sex: "女",
          age: 20,
        };
        render() {
          console.log(this);
          return (
            <ul>
              <li>姓名:{this.props.name}</li>
              <li>性别:{this.props.sex}</li>
              <li>年齡:{this.props.age}</li>
            </ul>
          );
        }
      }

      const p = { name: "小數", sex: "男" };
      // 虛拟元素渲染
      ReactDOM.render(
        <Mycompent {...p} {...say} />,
        document.getElementById("example")
      );

      // 傳遞方法
      function say() {
        console.log("調用方法了");
      }
    </script>
  </body>
</html>

           

2.5.2.4 函數式元件props

<!--
 * @Description: 函數式元件props
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-03 22:19:32
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 16:10:34
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      // 定義類元件
      function Mycompent(props) {
        const { name, sex, age } = this.props;
        return (
          <ul>
            <li>姓名:{name}</li>
            <li>性别:{sex}</li>
            <li>年齡:{age}</li>
          </ul>
        );
      }
      // 類型檢查
      Mycompent.propTypes = {
        // 限制為字元串,且必須要
        name: PropTypes.string.isRequired,
        sex: PropTypes.string,
        age: PropTypes.number,
      };
      // 指定标簽預設值
      Mycompent.defaultProps = {
        sex: "女",
        age: 20,
      };

      // 虛拟元素渲染
      ReactDOM.render(
        <Mycompent name="小數" sex="男" age={12} />,
        document.getElementById("example")
      );
    </script>
  </body>
</html>

           

2.5.2.5 總結

  • state 和 props 主要的差別在于 props 是不可變的,而 state 可以根據與使用者互動來改變。這就是為什麼有些容器元件需要定義 state 來更新和修改資料。 而子元件隻能通過 props 來傳遞資料。

props:

  • props:函數元件的props就是函數的入參元件
  • 類元件:this.props包含被該元件調用或者定義的props

state:

  • 元件中的state包含了随時可能發生變化的資料。
  • state是由使用者定義,是一個普通的JavaScript對象

差別:

  • props是傳遞給元件的(類似于函數的形參),而state是在元件内部被元件自己管理的(類似于在一個函數内聲明的變量)
  • props是不可以被修改的,所有的react元件都必須像純函數一樣保護他們的props不被修改
  • state是在元件中建立,一般是在constructor中初始化state
  • state是多變的,可被修改的。每次setState都是異步更新的

2.5.3 核心元件執行個體:Ref

React 基本文法入門一 React簡介二 React 基本文法Hello, World

在React的開發模式中,通常情況下不需要、也不建議直接操作DOM原生,但是某些特殊的情況,确實需要擷取到DOM進行某些操作:

  • 管理焦點,文本選擇或媒體播放;
  • 觸發強制動畫;
  • 內建第三方 DOM 庫;

是以當我們需要操作DOM時,我們就需要來使用Ref

2.5.3.1 方法一:傳入字元串(不推薦使用)

使用時通過 this.refs.傳入的字元串格式擷取對應的元素;

<!--
 * @Description:字元串的ref
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-05 16:59:51
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 17:10:10
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
    <script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      // 定義類元件
      class Mycompent extends React.Component {
        showData01 = () => {
          console.log(this);
          const { input1 } = this.refs;
          alert(input1.value);
        };

        showData02 = () => {
          console.log(this);
          const { input2 } = this.refs;
          alert(input2.value);
        };

        render() {
          return (
            <div>
              <input ref="input1" type="text" placeholder="點選按鈕提示資料" />
              &nbsp;
              <button onClick={this.showData01}>點選提示</button>
              &nbsp;
              <input
                ref="input2"
                onBlur={this.showData02}
                type="text"
                placeholder="失去焦點提示資料"
              />
            </div>
          );
        }
      }
      // 虛拟元素渲染
      ReactDOM.render(<Mycompent />, document.getElementById("example"));
    </script>
  </body>
</html>

           
React 基本文法入門一 React簡介二 React 基本文法Hello, World
React 基本文法入門一 React簡介二 React 基本文法Hello, World
React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.5.3.2 方法二:回調函數

傳入一個函數該函數會在DOM被挂載時進行回調,這個函數會傳入一個 元素對象,我們可以自己儲存;使用時,直接拿到之前儲存的元素對象即可;

<!--
 * @Description:函數式回調的ref
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-05 16:59:51
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 17:51:44
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
    <script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      // 定義類元件
      class Mycompent extends React.Component {
        showData01 = () => {
          console.log(this);
          const { input1 } = this;
          alert(input1.value);
        };

        showData02 = () => {
          console.log(this);
          const { input2 } = this;
          alert(input2.value);
        };

        render() {
          return (
            <div>
              <input
                ref={c=>this.input1=c}
                type="text"
                placeholder="點選按鈕提示資料"
              />
              &nbsp;
              <button onClick={this.showData01}>點選提示</button>
              &nbsp;
              <input
                ref={c=>this.input2=c}
                onBlur={this.showData02}
                type="text"
                placeholder="失去焦點提示資料"
              />
            </div>
          );
        }
      }
      // 虛拟元素渲染
      ReactDOM.render(<Mycompent />, document.getElementById("example"));
    </script>
  </body>
</html>

           
React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.5.3.3 方法三:creatRef

使用此方法來建立ref。将其指派給一個變量,通過ref挂載在dom節點或元件上,該ref的current屬性,将能拿到dom節點或元件的執行個體

<!--
 * @Description:creatRef的ref
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-05 16:59:51
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 21:57:04
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
    <script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      // 定義類元件
      class Mycompent extends React.Component {
        myRef = React.createRef();
        myRef02 = React.createRef();
        showData01 = () => {
          console.log(this.myRef);
          const { current } = this.myRef;
          alert(current.value);
        };

        showData02 = () => {
          console.log(this.myRef02);
          const { current } = this.myRef02;
          alert(current.value);
        };

        render() {
          return (
            <div>
              <input
                ref={this.myRef}
                type="text"
                placeholder="點選按鈕提示資料"
              />
              &nbsp;
              <button onClick={this.showData01}>點選提示</button>
              &nbsp;
              <input
                ref={this.myRef02}
                onBlur={this.showData02}
                type="text"
                placeholder="失去焦點提示資料"
              />
            </div>
          );
        }
      }
      // 虛拟元素渲染
      ReactDOM.render(<Mycompent />, document.getElementById("example"));
    </script>
  </body>
</html>

           

2.5.4 事件總結

  • React的事件是通過onXxx屬性指定事件處理函數
  • React使用的都是自定義的事件,而不是原生的事件
  • React中的事件是通過事件委托方式處理的
  • 事件中必須傳回的是函數
  • 通過event.target得到發生事件的Dom元素對象

2.5.5 受控元件與非受控元件

非受控元件

非受控元件其實就是表單元素的值不會更新state。輸入資料都是現用現取的。有點像雙向綁定

class Login extends React.Component{
    login = (event) =>{
       		 event.preventDefault(); //阻止表單送出
            console.log(this.name.value);
            console.log(this.pwd.value);
        }
        render() {
            return (
                <form action="http://www.baidu.com" onSubmit={this.login}>
                使用者名:<input ref = {c => this.name =c } type = "text" name ="username"/>
                密碼:<input ref = {c => this.pwd =c } type = "password" name ="password"/>
                <button>登入</button>
                </form>
            )
    }
}
           

受控元件

使 React 的 state 成為“唯一資料源”。渲染表單的 React 元件還控制着使用者輸入過程中表單發生的操作。被 React 以這種方式控制取值的表單輸入元素就叫做“受控元件”。

state={
  name:'',
  pwd:''
}

saveName = (event) =>{
    this.setState({name:event.target.value});
}

savePwd = (event) => {
    this.setState({pwd:event.target.value});
}

render() {
    return (
        <form action="http://www.baidu.com" onSubmit={this.login}>
            使用者名:<input value={this.state.name} onChange={this.saveName} type = "text" />
            密碼<input value={this.state.pwd} onChange={this.savePwd} type = "password"/>
            <button>登入</button>
        </form>
    )
}
           

2.6 生命周期

2.6.1 案例引入

<!--
 * @Description:生命周期
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-06 14:04:05
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-06 14:44:48
-->
<!--
 * @Description: state的初步使用
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-03 22:19:32
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 10:29:22
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      class MyLife extends React.Component {
        // 狀态
        state = { opacity: 1 };
        // 點選事件
        death = () => {
          // 移除元件
          ReactDOM.unmountComponentAtNode(document.getElementById("example"));
        };

        // 元件挂載頁面時調用
        componentDidMount() {
          this.timer = setInterval(() => {
            let { opacity } = this.state;
            opacity -= 0.1;
            if (opacity < 0) opacity = 1;
            this.setState({ opacity: opacity });
          }, 200);
        }

        // 元件将要解除安裝
        componentWillUnmount() {
          // 清除定時器
          clearInterval(this.timer);
        }

        // 渲染
        render() {
          return (
            <div>
              <h2 style={{ opacity: this.state.opacity }}>React學不會咋辦?</h2>
              <button onClick={this.death}>不活了</button>
            </div>
          );
        }
      }
      // 虛拟元素渲染
      ReactDOM.render(<MyLife />, document.getElementById("example"));
    </script>
  </body>
</html>

           
React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.6.2 生命周期(舊 16)

React的生命周期從廣義上分為三個階段:挂載、渲染、解除安裝

是以可以把React的生命周期分為兩類:挂載解除安裝過程和更新過程。

React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.6.2.1 初始化階段

constructor()

constructor()中完成了React資料的初始化,它接受兩個參數:props和context,當想在函數内部使用這兩個參數時,需使用super()傳入這兩個參數。

注意:隻要使用了constructor()就必須寫super(),否則會導緻this指向錯誤。

componentWillMount()

componentWillMount()一般用的比較少,它更多的是在服務端渲染時使用。它代表的過程是元件已經經曆了constructor()初始化資料後,但是還未渲染DOM時。

componentDidMount()

元件第一次渲染完成,此時dom節點已經生成,可以在這裡調用ajax請求,傳回資料setState後元件會重新渲染

componentWillUnmount()

在此處完成元件的解除安裝和資料的銷毀:clear你在組建中所有的setTimeout,setInterval,移除所有組建中的監聽 removeEventListener

<!--
 * @Description:生命周期
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-06 14:04:05
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-06 16:05:12
-->
<!--
 * @Description: state的初步使用
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-03 22:19:32
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-05 10:29:22
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- react表達式 -->
    <script type="text/babel">
      class MyLife extends React.Component {
        constructor(props) {
          console.log("01構造函數");
          super(props);
        }
        // 狀态
        state = { opacity: 1 };
        // 點選事件
        death = () => {
          // 移除元件
          ReactDOM.unmountComponentAtNode(document.getElementById("example"));
        };

        // 元件挂載頁面時調用
        componentDidMount() {
            console.log('04元件将要挂載')
          this.timer = setInterval(() => {
            let { opacity } = this.state;
            opacity -= 0.1;
            if (opacity < 0) opacity = 1;
            this.setState({ opacity: opacity });
          }, 200);
        }

        //元件将要挂載時候觸發的生命周期函數
        componentWillMount() {
          console.log("02元件将要挂載");
        }

        // 元件将要解除安裝
        componentWillUnmount() {
          // 清除定時器
          clearInterval(this.timer);
          console.log('05元件将要解除安裝')
        }

        // 渲染
        render() {
          console.log("03資料渲染render");
          return (
            <div>
              <h2 style={{ opacity: this.state.opacity }}>React學不會咋辦?</h2>
              <button onClick={this.death}>不活了</button>
            </div>
          );
        }
      }
      // 虛拟元素渲染
      ReactDOM.render(<MyLife />, document.getElementById("example"));
    </script>
  </body>
</html>

           
React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.6.2.2 更新階段

componentWillReceiveProps ()

這個函數也就是當我們父元件給子元件傳值的時候改變了props的值時觸發的函數,初始化第一次時不會調用,當父元件傳值進行更新,才發生變化。

shouldComponentUpdate()

資料更新的話第一步是shouldComponentUpdate确認是否要更新資料,當這個函數傳回的是true的時候才會進行更新,并且這個函數可以聲明兩個參數nextProps和nextState,

nextProps是父元件傳給子元件的值,nextState是資料更新之後值,這兩個值可以在這個函數中擷取到。第二步當确認更新資料之後componentWillUpdate将要更新資料,第三步依舊是render,資料發生改變render重新進行了渲染。第四步是componentDidUpdate資料更新完成。

componentWillUpdate()

shouldComponentUpdate傳回true以後,元件進入重新渲染的流程,進入componentWillUpdate,這裡同樣可以拿到nextProps和nextState。

componentDidmount()

元件更新完畢後,react隻會在第一次初始化成功會進入componentDidmount,之後每次重新渲染後都會進入這個生命周期,這裡可以拿到prevProps和prevState,即更新前的props和state。

rende()

render函數會插入jsx生成的dom結構,react會生成一份虛拟dom樹,在每一次元件更新時,在此react會通過其diff算法比較更新前後的新舊DOM樹,比較以後,找到最小的有差異的DOM節點,并重新渲染。

<!--
 * @Description: 父元件與子元件的生命周期
 * @version: 1.0
 * @Author: shu
 * @Date: 2022-10-06 16:13:37
 * @LastEditors: 修改者填寫
 * @LastEditTime: 2022-10-06 16:17:53
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- 注意導入時依賴的順序 -->
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <script type="text/babel">
      class Father extends React.Component {
        // 構造器
        constructor(props) {
          super(props);
          this.state = {
            flag: true,
            title: "我是Father元件的标題",
          };
        }

        //建立/銷毀元件
        setFlag() {
          this.setState({
            flag: !this.state.flag,
          });
        }

        //改變title
        setTitle() {
          this.setState({
            title: "我是Father元件改變後的title",
          });
        }

        render() {
          return (
            <div className="Father">
              {this.state.flag ? <Son title={this.state.title} /> : ""}
              <button onClick={() => this.setFlag()}>
                挂載/銷毀生命周期函數元件
              </button>
              <button onClick={() => this.setTitle()}>
                改變app元件的title
              </button>
            </div>
          );
        }
      }
      // 子元件
      class Son extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            msg: "我是一個msg資料",
          };
        }
        //元件将要挂載時候觸發的生命周期函數
        componentWillMount() {
          console.log("02元件将要挂載");
        }
        //元件挂載完成時候觸發的生命周期函數
        componentDidMount() {
          //Dom操作,請求資料放在這個裡面
          console.log("04元件挂載完成");
        }
        //是否要更新資料,如果傳回true才會更新資料
        shouldComponentUpdate(nextProps, nextState) {
          console.log("01是否要更新資料");
          console.log(nextProps); //父元件傳給子元件的值,這裡沒有會顯示空
          console.log(nextState); //資料更新後的值
          return true; //傳回true,确認更新
        }
        //将要更新資料的時候觸發的
        componentWillUpdate() {
          console.log("02元件将要更新");
        }
        //更新資料時候觸發的生命周期函數
        componentDidUpdate() {
          console.log("04元件更新完成");
        }
        //你在父元件裡面改變props傳值的時候觸發的函數
        componentWillReceiveProps() {
          console.log("父子元件傳值,父元件裡面改變了props的值觸發的方法");
        }
        setMsg() {
          this.setState({
            msg: "我是改變後的msg資料",
          });
        }
        //元件将要銷毀的時候觸發的生命周期函數,用在元件銷毀的時候執行操作
        componentWillUnmount() {
          console.log("元件銷毀了");
        }
        render() {
          console.log("03資料渲染render");
          return (
            <div>
              生命周期函數示範--{this.state.msg}--{this.props.title}
              

              <hr />
              <button onClick={() => this.setMsg()}>更新msg的資料</button>
            </div>
          );
        }
      }
      // 虛拟元素渲染
      ReactDOM.render(<Father />, document.getElementById("example"));
    </script>
  </body>
</html>

           
React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.6.3 生命周期(新 17)

React 基本文法入門一 React簡介二 React 基本文法Hello, World

官網解釋:

最新的react版本中,有些生命周期鈎子被抛棄了,在官網中是這樣說的:

我們得到最重要的經驗是,過時的元件生命周期往往會帶來不安全的編碼實踐,具體函數如下:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

這些生命周期方法經常被誤解和濫用;此外,我們預計,在異步渲染中,它們潛在的誤用問題可能更大。我們将在即将釋出的版本中為這些生命周期添加 “UNSAFE_” 字首。(這裡的 “unsafe” 不是指安全性,而是表示使用這些生命周期的代碼在 React 的未來版本中更有可能出現 bug,尤其是在啟用異步渲染之後。)

由此可見,新版本中并不推薦持有這三個函數,取而代之的是帶有UNSAFE_ 字首的三個函數,比如: UNSAFE_ componentWillMount。即便如此,其實React官方還是不推薦大家去使用,在以後版本中有可能會去除這幾個函數

React 基本文法入門一 React簡介二 React 基本文法Hello, World

2.6.3.1 getDerivedStateFromProps(nextProps, prevState)

代替componentWillReceiveProps()。老版本中的componentWillReceiveProps()方法判斷前後兩個 props 是否相同,如果不同再将新的 props 更新到相應的 state 上去。這樣做一來會破壞 state 資料的單一資料源,導緻元件狀态變得不可預測,另一方面也會增加元件的重繪次數。(了解即可)

// before
componentWillReceiveProps(nextProps) {
  if (nextProps.isLogin !== this.props.isLogin) {
    this.setState({ 
      isLogin: nextProps.isLogin,   
    });
  }
  if (nextProps.isLogin) {
    this.handleClose();
  }
}

// after
static getDerivedStateFromProps(nextProps, prevState) {
  if (nextProps.isLogin !== prevState.isLogin) {
    return {
      isLogin: nextProps.isLogin,
    };
  }
  return null;
}

componentDidUpdate(prevProps, prevState) {
  if (!prevState.isLogin && this.props.isLogin) {
    this.handleClose();
  }
}

           

2.6.3.2 getSnapshotBeforeUpdate(prevProps, prevState)(更新)

代替componentWillUpdate。常見的 componentWillUpdate 的用例是在元件更新前,讀取目前某個 DOM 元素的狀态,并在 componentDidUpdate 中進行相應的處理。

這兩者的差別在于:

  1. 在 React 開啟異步渲染模式後,在 render 階段讀取到的 DOM 元素狀态并不總是和 commit 階段相同,這就導緻在

    componentDidUpdate 中使用 componentWillUpdate 中讀取到的 DOM 元素狀态是不安全的,因為這時的值很有可能已經失效了。

  2. getSnapshotBeforeUpdate 會在最終的 render 之前被調用,也就是說在 getSnapshotBeforeUpdate 中讀取到的 DOM 元素狀态是可以保證與 componentDidUpdate 中一緻的。

    此生命周期傳回的任何值都将作為參數傳遞給componentDidUpdate()。