<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
React Developer Tools
Ⅰ.函數式元件:
<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,隨後呈現在頁面中。
只能有一個根標籤
結束標籤
物件
(可以包含多個key-value的組合)更新元件的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>
<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>
render方法
中的this
為元件範例物件
自定義的方法
中this為undefined
,如何解決?①強制繫結this:通過函數物件的
bind()
②箭頭函數()=>{}
狀態資料,不能直接修改或更新,狀態必須通過setState進行修改
元件標籤
的所有屬性
都儲存在props
中 1.3.2 案例需求: 自定義用來顯示一個人員資訊的元件
效果如下:
標籤屬性
從元件外向元件內傳遞變化的資料元件內部不要修改props資料
,因為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)//列印所有屬性 }
<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>
元件內的標籤可以定義ref屬性
來標識自己(相當於原生裡是id)
需求: 自定義元件, 功能說明如下:
- 點選按鈕, 提示第一個輸入框中的值
- 當第2個輸入框失去焦點時, 提示這個輸入框中的值
<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 存在 一些問題。它已過時並可能會在未來的版本被移除。
效果如下:
<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>
效果如下:
<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 的繫結函數
的方式去避免上述的問題。
效果如下:
<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>
效果如下:
onXxx屬性
指定事件處理常式(注意大小寫
)通過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>
包含表單的元件分類
需求: 定義一個包含表單的元件
輸入使用者名稱密碼後, 點選登入提示輸入資訊
效果如下:
Ⅰ.非受控元件
對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>
到此這篇關於React元件三大屬性之state,props,refs的文章就介紹到這了,更多相關React元件屬性內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45