千峰React:函數組件使用(2)

前面寫了三千字沒保存,恨!

批量渲染

function App() {const list = [{id:0,text:'aaaa'},{id:1,text:'bbbb'},{id:2,text:'cccc'}]//   for (let i = 0; i < list.length; i++) {//     list[i] = <li>{list[i]}</li>//   }return (<div><ul>{list.map((item) => <li key={item.id}>{item.text}</li>)}</ul></div>)
}
export default App

點標記寫法

// function Welcome() {
//   return <div>hello Welcome</div>
// }// function App() {
//   return (
//     <div>
//       <Welcome />
//       <Welcome></Welcome>
//     </div>
//   )
// }
// export default Appconst Qf = () => {return <div>hello Qf</div>
}Qf.Welcome = () => {return <div>hello Welcome</div>
}function App() {return (<div><Qf.Welcome /><Qf.Welcome></Qf.Welcome></div>)
}
export default App

組件通信

import PropTypes from 'prop-types'
//子組件
function Welcome({ count, msg,isShow }) {return (<div>hello Welcome,{count},{msg},{isShow+''}</div>)
}// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.string.isRequired, // 驗證 count 是字符串并且是必傳的msg: PropTypes.string.isRequired, // 驗證 msg 是字符串并且是必傳的isShow: PropTypes.string.isRequired, // 驗證isShow是字符串并且是必傳的
}//父組件
function App() {const count='我是個變量'return (<div><Welcome count={count} msg='hi react' isShow /></div>)
}
export default App

組件組合

import PropTypes from 'prop-types'
//子組件
function Welcome() {return <div>hello Welcome</div>
}function Head() {return <div>hello Head</div>
}// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.string.isRequired, // 驗證 count 是字符串并且是必傳的msg: PropTypes.string.isRequired, // 驗證 msg 是字符串并且是必傳的isShow: PropTypes.string.isRequired, // 驗證isShow是字符串并且是必傳的
}//父組件
function App() {return (<div>hello App<Welcome><Head /></Welcome></div>)
}
export default App

可以看見這個Head被包在Welcome里 是渲染不出來的

使用props的children屬性傳遞子組件

import PropTypes from 'prop-types'function Head() {return <div>hello Head</div>
}function Welcome({ children }) {return (<div>hello Welcome{children}</div>)
}// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.string.isRequired, // 驗證 count 是字符串并且是必傳的children: PropTypes.string.isRequired, 
}//父組件
function App() {return (<div>hello App<Welcome><Head /></Welcome></div>)
}
export default App

另一種寫法

import PropTypes from 'prop-types'function Head({ count }) {return <div>hello Head,{count}</div>
}function Welcome() {const count = 456return (<div>hello Welcome<Head count={count} /></div>)
}
// 為 Head 組件添加 prop-types 驗證
Head.propTypes = {count: PropTypes.number.isRequired, // 驗證 count 是數字并且是必傳的
}// 添加 prop-types 驗證
Welcome.propTypes = {
}//父組件
function App() {return (<div>hello App<Welcome><Head /></Welcome></div>)
}
export default App

import PropTypes from 'prop-types'// 為 Head 組件添加 prop-types 驗證
Head.propTypes = {count: PropTypes.number.isRequired, // 驗證 count 是數字并且是必傳的
}// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.number.isRequired, // 驗證 Welcome 組件的 count 是必傳的
}function Head({ count }) {//接收countreturn <div>hello Head,{count}</div>
}function Welcome() {const count = 456return (<div>hello Welcome<Head count={count} />{/* {掛載count} */}</div>)
}//父組件
function App() {const count = 123return (<div>hello App<Welcome count={count} /></div>)
}
export default App

如何分別傳遞多組內容

所有的內容放到children里,沒辦法獨立使用

import PropTypes from 'prop-types'function Welcome({ children }) {return (<div>{children}hello Welcome{children}</div>)
}// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.string.isRequired, // 驗證 count 是字符串并且是必傳的children: PropTypes.string.isRequired,
}//父組件
function App() {return (<div>hello App<Welcome><div>aaaaaaaaaaaa</div><div>bbbbbbbbbbbb</div></Welcome></div>)
}
export default App

使用多組內容傳遞

import PropTypes from 'prop-types'function Welcome({ bottom, top }) {return (<div>{top}hello Welcome{bottom}</div>)
}// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.string.isRequired, // 驗證 count 是字符串并且是必傳的children: PropTypes.string.isRequired,top: PropTypes.string.isRequired,bottom: PropTypes.string.isRequired,
}//父組件
function App() {return (<div>hello App<Welcometop={<div>aaaaaaaaaaaa</div>}bottom={<div>bbbbbbbbbbbb</div>}></Welcome></div>)
}
export default App

通信的數據如何添加默認值

import PropTypes from 'prop-types'function Welcome({ count, msg }) {return (<div>hello Welcome,{count},{msg}</div>)
}// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.string.isRequired, // 驗證 count 是字符串并且是必傳的children: PropTypes.string.isRequired,msg: PropTypes.string.isRequired,
}//父組件
function App() {return (<div>hello App{/* { 傳遞參數的情況} */}<Welcome count={123} msg='hello react' />{/* { 不傳遞參數的情況} */}<Welcome /></div>)
}
export default App

如果有接收參數的位置,但是不傳遞參數,就會這樣👇

為了解決這個問題,就提供了默認參數

ES6是這么做的:

import PropTypes from 'prop-types'// function Head() {
//   return <div>hello Head</div>
// }function Welcome({ count='我是count的默認值', msg='我是msg的默認值'}) {return (<div>hello Welcome,{count},{msg}</div>)
}// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.string.isRequired, // 驗證 count 是字符串并且是必傳的children: PropTypes.string.isRequired,msg: PropTypes.string.isRequired,
}//父組件
function App() {return (<div>hello App{/* { 傳遞參數的情況} */}<Welcome count={123} msg='hello react' />{/* { 不傳遞參數的情況} */}<Welcome /></div>)
}
export default App

也可以使用React原生的:

import PropTypes from 'prop-types'function Welcome({ count,msg}) {return (<div>hello Welcome,{count},{msg}</div>)
}// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.number, // 驗證 count 是數字(非必傳)msg: PropTypes.string, // 驗證 msg 是字符串(非必傳)
}Welcome.defaultProps = {count: 0,msg:'我是默認值'
}
//父組件
function App() {return (<div>hello App{/* { 傳遞參數的情況} */}<Welcome count={123} msg='hello react' />{/* { 不傳遞參數的情況} */}<Welcome /></div>)
}
export default App

但是我失敗了

為什么?因為:

我是19,別管了就用es6吧

通信數據如何限定類型

一般更推薦ts,但是ts不一定是項目用的

類型驗證就用我之前已經寫過的這部分👇

// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.number, // 驗證 count 是數字(非必傳)msg: PropTypes.string, // 驗證 msg 是字符串(非必傳)
}

瀏覽器莫名其妙不報錯,可能還是react的版本問題

如果希望有個數據傳過來,數字和字符串都是符合要求的類型,也就是篩出兩種類型可以這么寫:

// 添加 prop-types 驗證
Welcome.propTypes = {count:PropTypes.oneOfType([PropTypes.string,PropTypes.number,]),// 驗證 count 是數字或字符串(非必傳)msg: PropTypes.string, // 驗證 msg 是字符串(非必傳)
}

還可以有一些更復雜的限定,比如限定值是多少:

import PropTypes from 'prop-types'function Welcome({ count, msg }) {return (<div>hello Welcome,{count},{msg}</div>)
}// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // 驗證 count 是數字或字符串(非必傳)msg: PropTypes.string, // 驗證 msg 是字符串(非必傳)type: PropTypes.oneOf(['primary', 'success', 'error']),
}Welcome.defaultProps = {count: 0,msg: '我是默認值',
}
//父組件
function App() {return (<div>hello App{/* { 正確的情況} */}<Welcome count={123} msg='hello react' type='我是錯的' /></div>)
}
export default App

這里按理來說應該會報錯,但是并沒有!!!

傳值其實也可以傳jsx:

import PropTypes from 'prop-types'function Welcome({ count, msg }) {return (<div>hello Welcome,{count},{msg}</div>)
}// 添加 prop-types 驗證
Welcome.propTypes = {count: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // 驗證 count 是數字或字符串(非必傳)msg: PropTypes.string, // 驗證 msg 是字符串(非必傳)type: PropTypes.oneOf(['primary', 'success', 'error']),icon: PropTypes.element//針對jsx的類型,element
}Welcome.defaultProps = {count: 0,msg: '我是默認值',
}
//父組件
function App() {return (<div>hello App{/* { 正確的情況} */}<Welcomecount={123}msg='hello react'type='primary'icon={<div className='icon-close'></div>}/></div>)
}
export default App

組件必須是個純函數

react的嚴格模式會檢測我們當前的組件是不是純函數

純函數組件是指:

  • 組件的輸出(渲染結果)完全由輸入(props 和 state)決定。

  • 組件沒有副作用(例如直接修改 DOM、發起網絡請求、使用?setTimeout?等)。

  • 組件在相同的 props 和 state 下,總是返回相同的渲染結果

兩次結果一樣

在嚴格模式下,React 會?故意調用兩次?函數組件(包括其渲染邏輯),如果組件是純函數,兩次調用的結果應該完全相同。

比如++操作,如果把對count的聲明寫函數外面,那么就不是一個純函數:

預期來說count=2,最后等于3是因為React故意調用兩次函數組件,兩次的結果一次為2,一次為3,所以不是純函數組件

這樣就是了

function App() {let count = 1count++console.log(count)return <div>{count}</div>
}
export default App

兩次結果相同

當然,不開嚴格模式的話就沒有這種情況啦,一般建議開啟

相同的輸入和輸出

意思就是給函數傳入相同的參數,就應該傳出相同的輸出

這是一個純函數,傳入2都是4

這不是純函數,傳入2得到的輸出不一定相同

純函數可以保證我們的組件更健壯

組件的狀態和useState

?useState基礎使用

useState 是一個 React Hook(函數),它允許我們向組件添加一個狀態變量(State), 從而控制影響組件的渲染結果

狀態變量是 React 組件內部的一個特殊變量,用于存儲組件的數據,當狀態變量的值發生變化時,React 會自動重新渲染組件,以反映最新的數據

狀態變量和普通JS變量不同的是,狀態變量一旦發生變化組件的視圖UI也會跟著變化(數據驅動視圖)

useState是React里的方法,返回的是個數組,數組里有兩項:[狀態變量,修改狀態變量的方法]

只有用這個專門的修改狀態變量的方法修改變量,才會在ui渲染里起效

//useState實現一個計數器按鈕
import { useState } from 'react'
function App() {// const handleClick = (name,e) => console.log('button被點擊了name:',name,'e:',e)//1、調用useState添加一個狀態變量const [count, setCount] = useState(0)//2、點擊事件回調const handleClick = () => { setCount(count+1) }return (<div className="App"><button onClick={handleClick}>{count}</button></div>);
}
export default App;

count++?會直接修改?count?的值,而 React 的狀態變量是不可變的(Immutable),不能直接修改。

那我就要問了:const handleClick = () => { setCount(count++) }這么寫不也是通過setState 函數更新狀態嗎?為什么不行?

count++ 會先返回當前的值,再進行自增操作,而 React 的 setState 需要傳入新的值,而不是修改原值。

那++count呢?++count 會先對 count 進行自增操作,然后返回自增后的值。這個操作會直接修改當前 count 的值,而 React 需要的是通過 setCount 來觸發狀態的更新,這就相當于狀態變量的修改是你自己改的,不是通過對應的方法改的

正確的寫法是應該直接傳入 count + 1,而不是 count++,因為 count++ 只是修改了本地變量

對于對象來說也是這樣,應該把新的對象寫進對應方法,而不是直接修改

import { useState } from 'react'function App () {let [count, setCount] = useState(0)const handleClick = () => {// 直接修改 無法引發視圖更新// count++// console.log(count)setCount(count + 1)}// 修改對象狀態const [form, setForm] = useState({ name: 'jack' })const changeForm = () => {// 錯誤寫法:直接修改// form.name = 'john'// 正確寫法:setFrom 傳入一個全新的對象setForm({...form,name: 'john'})}return (<div><button onClick={handleClick}>{count}</button><button onClick={changeForm}>修改form{form.name}</button></div>)
}export default App

狀態如何改變視圖

先看這段代碼

function App() {let count = 0const increment = () => {count++ // 修改普通變量console.log(count) // 值會變化,但不會觸發重新渲染}console.log(1234567)return (<div><p>{count}</p><button onClick={increment}>Increment</button></div>)
}
export default App

    點擊按鈕時,count?的值會增加,但頁面不會重新渲染,因此用戶看不到變化。

    狀態變量會被記憶上一次的值,每次渲染函數返回的內容不一樣,所以在察覺變化的時候React會重新調用渲染函數,并且改變count,所以每次結果都不一樣)

    普通變量的變化不會通知 React,所以React 不會調用渲染函數,所以不會重新渲染jsx。

    順便:Mujica第八集拍出來其實是為了縮短中國人壽命降低生產力,是日本人為了打敗中國人投放的精神類武器,是日本成為東亞第一強國的邪惡計劃最核心的一步

    本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
    如若轉載,請注明出處:http://www.pswp.cn/bicheng/71706.shtml
    繁體地址,請注明出處:http://hk.pswp.cn/bicheng/71706.shtml
    英文地址,請注明出處:http://en.pswp.cn/bicheng/71706.shtml

    如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

    相關文章

    Hot100 動態規劃

    動態規劃 動規五部曲&#xff1a; 確定dp數組以及下標的含義確定遞推公式dp數組如何初始化確定遍歷順序舉例推導dp數組 70. 爬樓梯 - 力扣&#xff08;LeetCode&#xff09; 爬到第一層樓梯有一種方法&#xff0c;爬到二層樓梯有兩種方法。 那么第一層樓梯再跨兩步就到第三…

    Rust語言基礎知識詳解【一】

    1.在windows上安裝Rust Windows 上安裝 Rust 需要有 C 環境&#xff0c;以下為安裝的兩種方式&#xff1a; 1. x86_64-pc-windows-msvc&#xff08;官方推薦&#xff09; 先安裝 Microsoft C Build Tools&#xff0c;勾選安裝 C 環境即可。安裝時可自行修改緩存路徑與安裝路…

    文章精讀篇——OMG-Seg

    題目&#xff1a;OMG-Seg : Is One Model Good Enough For All Segmentation? 作者&#xff1a;Xiangtai Li1 ? Haobo Yuan1 Wei Li1 Henghui Ding1 Size Wu1 Wenwei Zhang1Yining Li2 Kai Chen2 Chen Change Loy1 代碼&#xff1a;OMG-Seg 會議&#xff1a;cvpr2024 邊讀…

    vite 開啟 gzip壓縮

    使用vite 如何開啟 gzip壓縮 文章目錄 使用vite 如何開啟 gzip壓縮1. 引言為什么需要 Gzip 壓縮&#xff1f;Gzip 壓縮的作用 2. Vite 項目中的 Gzip 壓縮Vite 的基本概念Gzip 壓縮的原理 3. 使用 Vite 插件開啟 Gzip 壓縮安裝 vite-plugin-compression配置 vite-plugin-compre…

    【Qt學習】| 如何使用QVariant存儲自定義類型

    QVariant是Qt框架中的一個通用數據類型&#xff0c;可以存儲多種類型的數據&#xff0c;主要作用是提供一種類型安全的方式來存儲和傳遞不同類型的數據&#xff0c;而不需要顯示地指定數據類型。 QVariant提供了諸多構造函數可以非常方便地對基礎數據類型&#xff08;如&#x…

    【Python量化金融實戰】-第1章:Python量化金融概述:1.4 開發環境搭建:Jupyter Notebook、VS Code、PyCharm

    在量化金融開發中&#xff0c;選擇合適的開發環境至關重要。本章介紹三種主流工具&#xff1a;Jupyter Notebook&#xff08;交互式分析&#xff09;、VS Code&#xff08;輕量級編輯器&#xff09;、PyCharm&#xff08;專業IDE&#xff09;&#xff0c;并通過實戰案例展示其應…

    查看 nginx 是否已經啟動

    在 Ubuntu 或其他 Linux 系統上&#xff0c;要查看 Nginx 是否已經啟動&#xff0c;您可以使用以下幾種方法之一&#xff1a; 方法一&#xff1a;使用 systemctl 命令 Nginx 通常作為 systemd 服務運行&#xff0c;因此您可以使用 systemctl 命令來檢查其狀態。 打開終端。 …

    解釋 Vue 中的虛擬 DOM,如何通過 Diff 算法最小化真實 DOM 更新次數?

    1. 虛擬DOM核心原理&#xff08;附代碼示例&#xff09; // 簡化的VNode結構示意 class VNode {constructor(tag, data, children) {this.tag tag // 標簽名this.data data // 屬性/指令等this.children children // 子節點數組} }// 兩個新舊虛擬節點樹示例 const oldV…

    Pytorch使用手冊-音頻數據增強(專題二十)

    音頻數據增強 torchaudio 提供了多種方式來增強音頻數據。 在本教程中,我們將介紹一種應用效果、濾波器、RIR(房間脈沖響應)和編解碼器的方法。 最后,我們將從干凈的語音合成帶噪聲的電話語音。 import torch import torchaudio import torchaudio.functional as Fprin…

    Linux-Ansible模塊擴展

    文章目錄 Archive UnarchiveSetup模塊Lineinfile Replace &#x1f3e1;作者主頁&#xff1a;點擊&#xff01; &#x1f916;Linux專欄&#xff1a;點擊&#xff01; ??創作時間&#xff1a;2025年02月23日18點11分 Archive Unarchive Archive和Unarchive模塊 需求&#x…

    Redhat及其衍生系統安裝python

    目錄 更新包列表 安裝 Python 3 安裝特定版本的 Python 驗證安裝 安裝 pip 更新包列表 在安裝任何軟件之前&#xff0c;建議先更新系統的包列表&#xff0c;以確保安裝的是最新版本的軟件包&#xff1a; sudo dnf update 安裝 Python 3 RHEL 9 默認安裝了 Python 3&…

    Python條件控制和循環語句

    目錄 條件控制語句 1. if 語句 2. if-else 語句 3. if-elif-else 語句 循環語句 1. for 循環 2. while 循環 循環控制語句 1. break 語句 2. continue 語句 3. else 子句&#xff08;與循環結合&#xff09; 嵌套循環 常見應用場景 條件控制 循環語句 條件控制語…

    *PyCharm 安裝教程

    PyCharm 安裝教程&#xff0c;適用于 Windows、macOS 和 Linux 系統&#xff1a; 1. 下載 PyCharm 官網地址&#xff1a;https://www.jetbrains.com/pycharm/版本選擇&#xff1a; Community&#xff08;社區版&#xff09;&#xff1a;免費&#xff0c;適合基礎 Python 開發…

    Three.js 快速入門教程【二】透視投影相機

    系列文章目錄 系列文章目錄 Three.js 快速入門教程【一】開啟你的 3D Web 開發之旅 Three.js 快速入門教程【二】透視投影相機 Three.js 快速入門教程【三】渲染器 Three.js 快速入門教程【四】三維坐標系 Three.js 快速入門教程【五】動畫渲染循環 Three.js 快速入門教程【六…

    IntelliJ IDEA 控制臺輸出中文出現亂碼

    IntelliJ IDEA 控制臺輸出中文出現亂碼通常是由于編碼設置不一致導致的。以下是常見原因及解決方法 1. 項目編碼設置 檢查路徑&#xff1a;File → Settings → Editor → File Encodings 確保 Project Encoding、Global Encoding 和 Default Encoding for Properties Files 均…

    C#初級教程(7)——初級期末檢測

    練習 1&#xff1a;計算圓的周長和面積 改編題目&#xff1a;編寫一個 C# 程序&#xff0c;讓用戶輸入圓的半徑&#xff0c;然后計算并輸出該圓的周長和面積&#xff0c;結果保留兩位小數。 using System;class CircleCalculation {static void Main(){const double pi 3.14…

    Java 集合:單列集合和雙列集合的深度剖析

    引言 在 Java 編程中&#xff0c;集合是一個非常重要的概念。它就像是一個容器&#xff0c;能夠存儲多個數據元素&#xff0c;幫助我們更方便地管理和操作數據。Java 集合框架主要分為單列集合和雙列集合兩大類&#xff0c;它們各自有著獨特的特點和適用場景。接下來&#xff0…

    layui 遠程搜索下拉選擇組件(多選)

    模板使用&#xff08;lay-module/searchSelect&#xff09;&#xff0c;依賴于 jquery、layui.dist 中的 dropdown 模塊實現&#xff08;所以data 格式請參照 layui文檔&#xff09; <link rel"stylesheet" href"layui-v2.5.6/dist/css/layui.css" /&g…

    通俗易懂的DOM1級標準介紹

    前言 在前端開發中&#xff0c;DOM&#xff08;文檔對象模型&#xff09;是我們操作網頁內容的核心工具。前面的文章我們介紹了DOM0級、DOM2級事件模型&#xff0c;沒有DOM1級事件模型這種概念&#xff0c;但有DOM1級標準。今天我們就來討論DOM1級標準&#xff0c;看看它到底做…

    python~http的請求參數中攜帶map

    背景 調試 http GET請求的 map 參數&#xff0c;鏈路攜帶參數一直有問題&#xff0c;最終采用如下方式攜帶map 解決 user{"demo":"true","info":"王者"}url encode之后的效果如下所示 user%7B%22demo%22:%22true%22,%22info%22:%22…