網站首頁 編程語言 正文
1.1基本理解和使用
1.1.1 使用React開發者工具調試
React Developer Tools
1.1.2 定義組件的方式
Ⅰ.函數式組件:
<script type="text/babel"> // 1.創建函數式組件 (首字母必須大寫) function MyComponent() { //(函數必須有返回值) console.log(this) //undefined (本來this指向的是window,但是由于babel翻譯完之后啟用es5的嚴格模式,自定義的函數里的this不讓指向window) return <h2>我是用函數定義的組件(適用于【簡單組件】的定義)</h2> } // 2.渲染組件到頁面 (必須寫組件標簽) ReactDOM.render(<MyComponent />, document.getElementById('test')) </script>
執行了ReactDOM.render(…之后發生了什么?
1.React解析組件標簽,找到了MyComponent組件。
2.發現組件是使用函數定義的,隨后調用該函數,將返回的虛擬DOM轉為真實DOM,隨后呈現在頁面中。
類的基本知識復習移步到vscode
Ⅱ.類式組件:
復雜組件:如果組件是有狀態的,那么就是復雜組件。
<script type="text/babel"> // 1.創建類式組件 class MyComponent extends React.Component { render() { // render是放在哪里的?——MyComponent的原型對象上,供實例使用 // render中的this是誰?——MyComponent的實例對象 <=> MyComponent組件實例對象 console.log('render中的this是誰:', this) return <h2>我是用類定義的組件(適用于【復雜組件】的定義)</h2> } } // 渲染組件到頁面 ReactDOM.render(<MyComponent />, document.getElementById('test'))
執行了ReactDOM.render(…之后發生了什么?
1.React解析組件標簽,找到了MyComponent組件。
2.發現組件是使用類定義的,隨后new出來該類的實例,并通過該實例調用到原型上的render方法。
3.將render返回的虛擬DOM轉為真實DOM,隨后呈現在頁面中。
1.1.3 注意
- 組件名必須首字母大寫
- 虛擬DOM元素
只能有一個根標簽
- 虛擬DOM元素必須有
結束標簽
1.1.4 渲染類組件標簽的基本流程
- React內部會創建組件實例對象
- 調用render()返回得到虛擬DOM, 并解析為真實DOM
- 插入到指定的頁面元素內部
1.2 組件實例的三大核心屬性之一:state
1.2.1 理解
- state是組件對象最重要的屬性, 值是
對象
(可以包含多個key-value的組合) - 組件被稱為"狀態機", 通過
更新組件的state
,來更新對應的頁面顯示
(重新渲染組件) - 數據存放在狀態里,來驅動對應頁面的顯示
1.2.2 案例
需求: 定義一個展示天氣信息的組件
- 默認展示天氣炎熱 或 涼爽點
- 擊文字切換天氣
效果如下:
1.2.3 在類式組件使用state
<script type="text/babel"> // 1.創建組件 class Weather extends React.Component { // 借助構造器初始化狀態 // 構造器調用了幾次?————1次 constructor(props) { console.log('constructor') super(props) // 初始化狀態 this.state = { isHot: true, wind: '微風' } //解決changeWeather中this指向的問題 this.changeWeather = this.changeWeather.bind(this) // 這是一個賦值語句,右邊的this.changeWeather是指順著原型鏈找到了changeWeather(),然后調用bind(),bind可以生成一個新的函數,改變this指向。括號中為傳入的this,指得就是類中的實例對象 // 拿到了原型上的changeWeather,通過bind生成了一個新的changeWeather掛在實例自身 } // render調用了幾次?————1+n次 1是初始化的那次,n是狀態更新的次數 render() { console.log('render') // 讀取狀態 const { isHot, wind } = this.state // react:將changeWeather調用的返回值賦值給onClick,不用加括號 // 原生js:onclick時調用changeWeather函數,要加括號 return <h1 onClick={this.changeWeather}>今天天氣很{isHot ? '炎熱' : '涼爽'},{wind}</h1> // 含義是:這是一個賦值語句,把右邊這個函數交給onClick作為回調, // 等你點擊的時候,react幫你調changeWeather()函數 } // changeWeather調用了幾次?————點幾次調幾次 changeWeather() { console.log('changeWeather') // changeWeather放在哪里?——Weather的原型對象上,供實例使用 // 通過Weather實例調用changeWeather時,changeWeather中的this就是Weather實例 console.log(this) //undefined // 因為changeWeather不是通過實例調用的,是直接調用,所以this不會指向 實例對象 // 那么 changeWeather 的this 是指向 undefined還是 window呢 // 是 undefined 因為 類中的局部函數默認開啟了嚴格模式(類自動開的,與babel無關),所以不能指向 window // 獲取原來的isHot值 const isHot = this.state.isHot // 嚴重注意:狀態(state)里的數據不能直接進行更改,下面這行就是直接更改,react不認可!!! // this.state.isHot = !isHot 錯誤寫法 // 嚴重注意:狀態必須通過setState進行修改,并且修改是一種合并,不是替換,只修改了isHot,wind不會丟失 this.setState({ isHot: !isHot }) } } // 2.渲染組件到頁面 ReactDOM.render(<Weather />, document.getElementById('test')) </script>
1.2.4 在類式組件使用state的簡寫方式
<script type="text/babel"> // 1.創建組件 class Weather extends React.Component { // 初始化狀態時直接在類里面寫賦值語句 state = { isHot: true, wind: '微風' } render() { const { isHot, wind } = this.state return <h1 onClick={this.changeWeather}>今天天氣很{isHot ? '炎熱' : '涼爽'},{wind}</h1> } // 自定義方法 ————在用類去創建一個組件時,組件里所有自定義的方法都要用 賦值語句+箭頭函數 的形式 changeWeather = () => { //箭頭函數沒有this,箭頭函數內的this指向其外側 const isHot = this.state.isHot this.setState({ isHot: !isHot }) console.log(this) } } ReactDOM.render(<Weather />, document.getElementById('test')) </script>
1.2.3 強烈注意
- 組件中
render方法
中的this
為組件實例對象
- 組件
自定義的方法
中this為undefined
,如何解決?
①強制綁定this:通過函數對象的
bind()
②箭頭函數()=>{}
狀態數據,不能直接修改或更新,狀態必須通過setState進行修改
1.3 組件實例的三大核心屬性之一:props
1.3.1 理解
- 每個組件對象都會有props(properties 的簡寫)屬性
-
組件標簽
的所有屬性
都保存在props
中 1.3.2 案例
需求: 自定義用來顯示一個人員信息的組件
- 姓名必須指定,且為字符串類型
- 性別為字符串類型,如果性別沒有指定,默認為男
- 年齡為字符串類型,且為數字類型,默認值為18
效果如下:
1.3.3 作用
- 通過
標簽屬性
從組件外向組件內傳遞變化的數據 - 注意:
組件內部不要修改props數據
,因為props是只讀的
1.3.4 在類式組件使用props
先從內部讀取某個屬性值:
//實例對象身上有個屬性props,需要傳值進去,那怎么傳呢?html標簽能寫標簽屬性(key:value),那么組件標簽(<Person/>)也能寫屬性 // 解構賦值 提前從props身上拿到這三個屬性 const { name, age, sex } = this.props
對props中的屬性值進行類型限制和必要性限制:
第一種方式(React v15.5 開始已棄用):
Person.propTypes = { name: React.PropTypes.string.isRequired, age: React.PropTypes.number }
第二種方式(新):使用prop-types庫進限制(需要引入prop-types庫)
//給Person加上propTypes屬性,react就能幫你限制了 //寫在Person類外面 Person.propTypes = { // 具體的propTypes規則,要去PropTypes(React里面內置的一個屬性)里面找 name: PropTypes.string.isRequired, //限制name必傳,且為字符串 age: PropTypes.number //限制age為數值 }
在類式組件使用props的簡寫方式
// 用static表示給類自身加上一個propTypes和defaultProps屬性,而不是給類的實例對象加屬性 // 寫在Person類里面 static propTypes = { name: PropTypes.string.isRequired, //限制name必傳,且為字符串 sex: PropTypes.string, //限制sex為字符串 age: PropTypes.number, //限制age為數值 } static defaultProps = { sex: '男', //sex默認值為不男不女 age: 18 //age默認值為18 }
擴展屬性: 將對象的所有屬性
通過props傳遞
// 展開運算符在對對象使用時,應當注意以{}包裹起來 <Person {...person}/> //...展開運算符具體運用看vscode
默認屬性值:
Person.defaultProps = { age: 18, //age默認值為18 sex:'男'//sex默認值為男 }
組件類的構造函數:
//開發中很少寫構造器,能省則省 // 構造器是否接收props,是否傳遞給super,取決于:是否希望在構造器中通過this訪問props constructor(props){ // 只要寫了構造器,就一定要調用super(),一定要傳props super(props) console.log(props)//打印所有屬性 }
1.3.5 在函數式組件使用props
<script type="text/babel"> // 創建組件 //函數式組件能接收參數 function Person(props) { // console.log(props) const { name, sex, age } = props return ( <ul> <li>姓名:{name}</li> <li>性別:{sex}</li> <li>年齡:{age}</li> </ul> ) } Person.propTypes = { name: PropTypes.string.isRequired, //限制name必傳,且為字符串 sex: PropTypes.string, //限制sex為字符串 age: PropTypes.number, //限制age為數值 } Person.defaultProps = { sex: '男', //sex默認值為不男不女 age: 18 //age默認值為18 } ReactDOM.render(<Person name='旭旭' />, document.getElementById('test')) </script>
1.4 組件實例的三大核心屬性之一:refs與事件處理
1.4.1 理解
組件內的標簽可以定義ref屬性
來標識自己(相當于原生里是id)
1.4.2 效果
需求: 自定義組件, 功能說明如下:
- 點擊按鈕, 提示第一個輸入框中的值
- 當第2個輸入框失去焦點時, 提示這個輸入框中的值
1.4.3 字符串形式的ref
<script type="text/babel"> // 創建組件 class Demo extends React.Component { // 展示左側輸入框的數據 showData = () => { const { input1 } = this.refs alert(input1.value) } // 展示右側輸入框的數據 showData2 = () => { const { input2 } = this.refs alert(input2.value) } render() { return ( <div> <input ref="input1" type="text" placeholder="點擊按鈕提示數據" /> <button onClick={this.showData}>點我提示左側的數據</button> <input ref="input2" onBlur={this.showData2} type="text" placeholder="失去焦點提示數據" /> </div> ) } } //渲染組件 ReactDOM.render(<Demo />, document.getElementById('test')) </script>
過時的API:String 類型的 Refs
如果你之前使用過 React,你可能了解過之前的 API 中的 string 類型的 ref 屬性,例如
"textInput"
。你可以通過this.refs.textInput
來訪問 DOM 節點。我們不建議使用它,因為 string 類型的 refs 存在 一些問題。它已過時并可能會在未來的版本被移除。
效果如下:
1.4.4 回調形式的ref
<script type="text/babel"> // 創建組件 class Demo extends React.Component { // 展示左側輸入框的數據 showData = () => { const { input1 } = this alert(input1.value) } // 展示右側輸入框的數據 showData2 = () => { const { input2 } = this alert(input2.value) } // 回調函數的特點:你定義的,別人調的,最終執行了 // 回調函數的參數正是ref當前所處的那個input節點 render() { return ( <div> {/* 代碼執行步驟: */} {/* React加載Demo組件時,執行render函數內的jsx代碼,發現input中有ref屬性,屬性內容是一個箭頭函數,React就會幫我們調用這個回調函數,并且把當前的DOM傳進這個函數,這樣就可以接收到當前的DOM節點了,并把這個DOM放在組件實例自身上 */} {/* 箭頭函數接收到參數(當前的DOM節點)命名為(currentNode),將currentNode賦值給實例對象下的input1這個屬性 */} {/* 箭頭函數只有一個參數可以省略'()',箭頭函數右邊只有一條函數體可以省略'{}' */} {/*<input ref={currentNode => this.input1 = currentNode} type="<text>" placeholder="點擊按鈕提示數據" /> */} <input ref={(currentNode) => { this.input1 = currentNode }} type="text" placeholder="點擊按鈕提示數據" /> <button onClick={this.showData}>點我提示左側的數據</button> <input ref={(currentNode) => { this.input2 = currentNode }} onBlur={this.showData2} type="text" placeholder="失去焦點提示數據" /> </div> ) } } //渲染組件 ReactDOM.render(<Demo />, document.getElementById('test')) </script>
效果如下:
1.4.5 回調ref中回調執行次數的問題(class的綁定函數)
<script type="text/babel"> // 創建組件 class Demo extends React.Component { state = { isHot: true } showInfo = () => { const { input1 } = this alert(input1.value) } changeWeather = () => { // 獲取原來的狀態 const { isHot } = this.state // 更新狀態 this.setState({ isHot: !isHot }) } savaInput = (currentNode) => { this.input1 = currentNode; } render() { const { isHot } = this.state return ( <div> <h1>今天天氣很{isHot ? '炎熱' : '涼爽'}</h1> {/* React在更新組件時,會先傳入null調用一次ref中的回調,以清空之前的ref;然后再傳入參數currentNode,以調用第二次。每更新一次組件,ref中的回調函數就會被調用兩次,一次傳入null,一次傳入參數currentNode。為了應對這種情況的出現,官方建議將ref的回調函數定義成 class 的綁定函數 的方式去避免上述的問題。 */} {/*內聯函數*/} {/*<input ref={(currentNode) => { this.input1 = currentNode; console.log('@', currentNode) }} type="text" /><br /><br />*/} <input ref={this.savaInput} type="text" /><br /><br /> <button onClick={this.showInfo}>點我提示輸入的數據</button> <button onClick={this.changeWeather}>點我切換天氣</button> </div> ) } } //渲染組件 ReactDOM.render(<Demo />, document.getElementById('test')) </script>
React在更新組件時,會先傳入null調用一次ref中的回調,以清空之前的ref;然后再傳入參數currentNode,以調用第二次。每更新一次組件,ref中的回調函數就會被調用兩次,一次傳入null,一次傳入參數currentNode。為了應對這種情況的出現,官方建議將ref的回調函數定義成
class 的綁定函數
的方式去避免上述的問題。
效果如下:
1.4.6 createRef創建ref容器
<script type="text/babel"> // 創建組件 class Demo extends React.Component { myRef = React.createRef() myRef2 = React.createRef() /* React.createRef調用后可以返回一個容器,該容器可以存儲被ref所標識的節點,該容器是“專人專用”的,也就是,調用React.createRef()創建了一個容器,通過賦值語句賦值給實例自身名為myRef的屬性上 */ // 展示左側輸入框的數據 showData = () => { // console.log(this.myRef) alert(this.myRef.current.value) } // 展示右側輸入框的數據 showData2 = () => { alert(this.myRef2.current.value) } // 回調函數的特點:你定義的,別人調的,最終執行了 // 回調函數的參數正是ref當前所處的那個input節點 render() { return ( <div> {/* React執行render函數中的jsx代碼時, 發現input上有一個ref屬性而且是通過createRef方法創建的, React就會把當前ref屬性所在的DOM節點放到之前創建的那個容器上, 也就是把當前input這個DOM節點放到了實例自身名為myRef的容器上 */} {/* 可以簡寫成ref={this.myRef = React.createRef()} */} <input ref={this.myRef} type="text" placeholder="點擊按鈕提示數據" /> <button onClick={this.showData}>點我提示左側的數據</button> {/* 發生事件的元素正好是需要操作的元素本身,可以省略ref */} <input ref={this.myRef2} onBlur={this.showData2} type="text" placeholder="失去焦點提示數據" /> </div> ) } } //渲染組件 ReactDOM.render(<Demo />, document.getElementById('test')) </script>
效果如下:
1.4.7 事件處理
- 通過
onXxx屬性
指定事件處理函數(注意大小寫
) - React使用的是自定義(合成)事件, 而不是使用的原生DOM事件-------為了更好的兼容性
- React中的事件是通過事件委托方式處理的(委托給組件最外層的元素)--------為了高效
通過event.target
得到發生事件的DOM元素對象------不要過度使用ref
<script type="text/babel"> // 創建一個組件 class Demo extends React.Component { showInfo = () => { alert(this.myRef.current.value) } showData = (event) => { // 傳入的event是發生onBlur事件的事件源,也就是失去焦點提示數據的input框, // 通過event.target.value拿到input中的值 alert(event.target.value) } render() { return ( <div> <input ref={this.myRef = React.createRef()} type="text" placeholder="點擊按鈕提示數據" /> <button onClick={this.showInfo}>點我提示左側數據</button> <input onBlur={this.showData} type="text" placeholder="失去焦點提示數據" /> </div> ) } } // 渲染組件到頁面 ReactDOM.render(<Demo />, document.getElementById('test')) </script>
1.5 收集表單數據
1.5.1 理解
包含表單的組件分類
- 受控組件
- 非受控組件
1.5.2 案例
需求: 定義一個包含表單的組件
輸入用戶名密碼后, 點擊登錄提示輸入信息
效果如下:
Ⅰ.非受控組件
對input(以及頁面中其他的一些輸入型DOM)中輸入的數據
現用現取
,就是非受控組件
<script type="text/babel"> // 創建一個組件 class Login extends React.Component { // handleSubmit函數中直接取出input中輸入的數據(現用現取) handleSubmit = (event) => { event.preventDefault() //阻止表單提交 const { username, password } = this alert(`你輸入的用戶名是: ${username.value}, 你輸入的密碼是: ${password.value}`) } render() { return ( // 對input(以及其他的一些輸入型DOM)中輸入的數據現用現取,就是非受控組件 <form onSubmit={this.handleSubmit}> 用戶名:<input ref={(c) => { this.username = c }} type="text" name="username" /> 密碼:<input ref={(c) => { this.password = c }} type="password" name="password" /> {/* form中的button默認提交,點擊后觸發表單提交事件onSubmit */} <button>登錄</button> </form> ) } } // 渲染組件到頁面 ReactDOM.render(<Login />, document.getElementById('test')) </script>
Ⅱ.受控組件
頁面中所有輸入類的DOM(input框),隨著用戶的輸入,能把輸入的東西維護到狀態里(
state
),等需要用時,直接從狀態里面取出來,就是受控組件
。(類似于vue里的雙向綁定
)
<script type="text/babel"> // 創建一個組件 class Login extends React.Component { // 初始化狀態 state = { username: '', password: '' } // 保存用戶名到狀態中 saveUsername = (event) => { this.setState({ username: event.target.value }) } // 保存密碼到狀態中 savePassword = (event) => { this.setState({ password: event.target.value }) } // 表單提交的回調 handleSubmit = (event) => { event.preventDefault() //阻止表單提交 const { username, password } = this.state alert(`你輸入的用戶名是: ${username}, 你輸入的密碼是: ${password}`) } /* 受控組件:(能夠省略ref) 頁面中所有輸入類的DOM(input框),隨著用戶的輸入,能把輸入的東西維護到狀態里(state),等需要用時,直接從狀態里面取出來 數據被onChange函數監聽,只要輸入型DOM數據一改變就觸發onChange中指定的回調函數 回調函數saveUsername和savePassword中對改變的數據進行保存,保存到state中,需要使用的時候才取出。 */ render() { return ( <form onSubmit={this.handleSubmit}> 用戶名:<input onChange={this.saveUsername} type="text" name="username" /> 密碼:<input onChange={this.savePassword} type="password" name="password" /> <button>登錄</button> </form> ) } } // 渲染組件到頁面 ReactDOM.render(<Login />, document.getElementById('test')) </script>
原文鏈接:https://blog.csdn.net/xuxuii/article/details/124989080
相關推薦
- 2022-04-20 python實現Simhash算法_python
- 2022-11-19 Python?numpy?ndarray屬性,索引,切片_python
- 2022-09-02 R語言which函數介紹及Rcpp改寫詳解_R語言
- 2022-10-01 React?hooks?useState異步問題及解決_React
- 2022-05-10 react設置多個classname
- 2023-04-08 C#字符串和Acsii碼相互轉換_C#教程
- 2022-11-03 Python入門教程之三元運算符的使用詳解_python
- 2023-07-02 一文詳解Python中logging模塊的用法_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支