? ? ? ? ? ?react開發我們會把頁面分為一個個組件,組件是獨立而且可復用的重復代碼片段。具體來說組件可以是一個按鈕,一個輸入框。react組件有兩種定義方法,一種是函數組件,一種是類組件。我們這里說一下函數組件之間父子之間如何傳遞props參數,如果通過ref來獲取真實DOM元素,如何通過設置state這個react變量去動態展示頁面中的數據。
?1.props
import React from 'react'
import LogItem from './LogItem'
import './Log.css'
export default function Logs() {//模擬一組從服務器加載的數據const logsData = [{id: "001",data: new Date(2021, 9, 20, 19, 0),title: '學習九陽神功',time: 30},{id: "002",data: new Date(2021, 4, 20, 19, 0),title: '學習我我我功',time: 20},{id: "003",data: new Date(2021, 5, 20, 19, 0),title: '學習你你神功',time: 10},{id: "004",data: new Date(2022, 1, 20, 19, 0),title: '學習九大大滴神功',time: 34}]return (// 如果組件中的數據全部寫死會導致組件無法動態設置//希望組件數據可以由外部設置 在組件間父組件可以通過props給子組件傳遞數據<div className='logs'>{/* 在父組件給子組件設置屬性在函數組件中可以通過參數來保存 */}{logsData.map((item) => {return (<LogItem key={item.id} data={item.data} title={item.title} time={item.time} />// <LogItem {...item} />)})}</div>)
}
? ? ? ? 這里我們在組件中定義了一個數組對象,作為服務器返回的json數據。我們想要一個列表去展示這些數據,每個列表都是相同的,所以我們需要一個子組件展示內容,父組件遍歷展示子組件就可以了。我們需要把數據傳給子組件,通過props傳遞方法就是之間傳,通過key=value這種方式直接傳遞,key不會作為參數,會作為內部特殊屬性保留。然后傳遞過去之后子組件去獲取然后展示。?
import React from 'react'
import MyDate from './MyDate'
import './LogItem.css'
export default function LogItem(props) {// console.log(props);// console.log(props.data);return (//函數組件的行參定義一個props props指向一個對象 包含父組件傳遞所有參數<div className="item"><MyDate data={props.data} /><div className="content"><h2 className='title'>{props.title}</h2><div className="time">{props.time}</div></div></div>)
}
? ? ? ?函數組件直接在參數里面props接收就可以了。輸出的props就是傳過來的那些props參數。然后{}里面寫表達式就可以動態展示了。props是父組件給子組件傳遞的方式。
2.ref
? ? ? ? 我們在開發用react框架開發時,如果需要操作真實DOM,我們可以通過DOM對象(document)去操作DOM,也可以直接從react獲取DOM對象,首先用鉤子函數useRef()去創建一個存儲DOM對象的容器,其實就是一個非常普通的對象,里面有一個current屬性僅此而已。
import React, { useRef } from 'react'
import './App.css'
import { useState } from 'react'
let temp
export default function App() {console.log('函數執行了');const h1Ref = useRef()//創建一個容器// const h1Ref = { current: undefined }console.log(temp === h1Ref);temp = h1Ref//這里永遠不相等因為每次都是生成新對象//直接用這種創建一個有current屬性的對象也可以console.log(h1Ref);const clickHandler = () => {// const header = document.getElementById('header')// alert(header)// header.innerHTML = '哈哈'//原生DOM操作DOM元素h1Ref.current.innerHTML = 'hah'}return (<div className='app'><h1>{a}</h1><h1 id='header' ref={h1Ref}>為上標題</h1><button onClick={add}>加</button><h1>{user.name}-----{user.age}</h1><button onClick={go}>2</button><button onClick={clickHandler}>點完</button></div>)
}
? ? ? ? 比如我們希望用按鈕去操作h1標簽里面的文本改變,用document操作就需要設置id,然后通過id獲取元素對象賦值給header,然后調用header.innerText=‘haha’ ,但是我們在react盡量避免使用dom因為會脫離react掌控。我們這里用鉤子函數去定義一個容器h1Ref然后給我們想要操作的DOM一個ref屬性值是容器,那么就存到了這個容器對象的current里面,控制臺可以看,而且只是一個簡單的js對象。我們可以直接定義一個對象去代替,屬性就是current。然后直接h1Ref.current.innerHTML='hha'操作h1的文本內容,只不過需要注意的是useRef()創建的容器只會生成一次,如果直接創建對象的話每次重新渲染都需要重新生成一個新的對象。所以如果我們需要保持一個不變的對象或者值,多次渲染不丟失重置就可以用uesRef比如我們關閉定時器用到的id
function MyComponent() {const timerRef = useRef(null); // 創建一個持久的容器對象useEffect(() => {timerRef.current = setInterval(() => console.log('hi'), 1000);}, []);return <button onClick={() => clearInterval(timerRef.current)}>停止</button>;
}
3.state?
? ? ? ? 當我們想要設置一個變量,而且這個變量動態的展示到頁面上面,我們就需要去用鉤子函數useState()去創建一個數組,前面是我們的變量,后面是一個函數,調用之后可以用回調函數去更新我們的變量。
????????
import React, { useRef } from 'react'
import './App.css'
import { useState } from 'react'
let temp
export default function App() {console.log('函數執行了');console.log(h1Ref);// let a =1let [a, setA] = useState(2)console.log(useState());//輸出的是一個數組前面是初始值后面是函數const result = useState(1)console.log(result);let fn = result[1]console.log('fn', fn)const [user, setUser] = useState({ name: 'sun', age: 11 })//點擊加數字增加 點擊減數字減少const add = () => {// a++// setA(a++)setA((preState) => {return preState + 1})}const go = () => {// user.name = 'gou'// setUser(user) //不會重新渲染因為修改的是原對象// const newUser = Object.assign({}, user)// newUser.name = 'gou'// setUser(newUser)//這個方法可以因為淺復制給一個新對象復制,地址是改變的// setUser({ name: 'zhu', age: 19 })setUser({ ...user, name: 'gou' })}return (<div className='app'><h1>{a}</h1><h1 id='header' ref={h1Ref}>為上標題</h1><button onClick={add}>加</button><h1>{user.name}-----{user.age}</h1><button onClick={go}>2</button><button onClick={clickHandler}>點完</button></div>)
}
? ? ? ? 我們如果直接let a = 1 然后我們點擊按鈕其實a改變了,但是頁面a不會改變,因為沒有重新渲染頁面。所以a++執行成功但是頁面a沒有變化,這時候我們用我們的鉤子函數useState()并且用數組結構的方法去設置a。然后我們調用setA這個方法,里面設置一個回調函數,preState是當前的變量a,然后返回更新后的新的變量a。然后重新調渲染頁面。
????????
????????state特點。1.state是一個被react管理的變量 通過setState()修改變量的值會觸發重新渲染,重新調用一個render(),然后重新diff比較之后更新然后用DOM轉化虛擬DOM對象為真實DOM,只有state發生變化才會重新渲染。state是一個對象 修改時使用新的對象替換已有對象,直接修改原有對象 不會生效因為地址沒變,當通過setState去修改一個state時不表示修改當前state,修改的是組件下一次渲染的state值。
????????2.setState()會觸發組件重新渲染 它是異步的,會排隊讓同步代碼執行完以后再執行重新渲染,所以當調用setState()需要用到舊state值一定要注意 有可能出現計算錯誤的情況,為了避免這種情況可以傳遞回調函數的形式 箭頭函數參數為當前最新的state