一. refs的使用##
React開發(fā)模式中擒贸,通常情況不需要橘沥,也不建議直接操作DOM元素窗轩,但是某些特殊的情況,確實需要獲取到DOM進行某些操作座咆。
- 管理焦點痢艺,文本選擇/媒體播放;
- 觸發(fā)強制動畫介陶;
- 集成第三方DOM庫堤舒。
如何創(chuàng)建refs來獲取對應(yīng)的DOM?三種方式哺呜。
1.1 創(chuàng)建方式
import React, { PureComponent, createRef } from 'react'
export default class App extends PureComponent {
constructor(props) {
super(props);
// 方法二
this.titleRef = createRef();
// 方法三
this.titleEl = null;
}
render() {
return (
<div>
{/* <h2 ref="字符串/對象/回調(diào)函數(shù)">Hello World</h2> */}
<h2 ref="titleRef">Hello React</h2>
{/* 2. 目前React推薦的方式 */}
<h2 ref={this.titleRef}>Hello React</h2>
{/* 3. */}
<h2 ref={arg => { this.titleEl = arg }}>Hello React</h2>
<button onClick={e => this.changeText()}>改變文本</button>
</div>
)
}
changeText() {
// 1. 使用方式一:字符串(不推薦植酥,后續(xù)可能刪除)
this.refs.titleRef.innerHTML = "Hello wwq"
// 2. 使用對象(推薦)
this.titleRef.current.innerHTML = "Hello wwq"
// 3. 使用回調(diào)函數(shù)
console.log(this.titleEl);
this.titleEl.innerHTML = "Hello jsx3"
}
}
- 傳入字符串
- 傳入一個對象,官方推薦弦牡,取的時候要導(dǎo)入createRef庫友驮,用其實例的current屬性。 - 傳入回調(diào)函數(shù)
1.2 ref節(jié)點類型
ref用于html元素時驾锰,構(gòu)造函數(shù)中使用React.createRef()創(chuàng)建的ref接收底層DOM元素作為其current屬性卸留。
ref用于自定義class組件時,ref對象接收組件的掛載實例作為其current屬性椭豫。
不能在函數(shù)組件上使用ref屬性耻瑟,因為他們沒有實例。
但有時赏酥,我們想要獲取函數(shù)組件中的某個DOM元素喳整。
這個時候我們可以通過React.forwardRef,之后學(xué)習(xí)hooks中使用refs裸扶。
二. 受控組件##
2.1 認識受控組件
- 在React中框都,HTML表單的處理方式和普通的DOM元素不太一樣;表單元素通常會保存在一些內(nèi)部的state呵晨。
- HTML中魏保,(input, textarea, select)之類的表單元素通常自己維護state熬尺,并根據(jù)用戶輸入進行更新。
- 而在React中谓罗,可變狀態(tài)mutable state通常保存在組件的state屬性中粱哼,并且只能通過使用setState()來更新。
- 我們將兩者結(jié)合起來檩咱,使React的state成為“唯一數(shù)據(jù)源”揭措;
- 渲染表單的React組件還控制著用戶輸入過程中表單發(fā)生的操作;
- 被React以這種方式控制取值的表單輸入元素就叫做“受控組件”刻蚯。
2.1.1 默認提交表單方式
2.2 常見表單的處理
- 通過給form綁定onSubmit事件來更改默認行為绊含。
- 給input綁定onChange事件來監(jiān)聽輸入變化。
- 為了輸入框和state中數(shù)據(jù)保持一致芦倒,我們需要同步到value艺挪,單向數(shù)據(jù)流:input中輸入,觸發(fā)onChange -> onChange調(diào)用handleChange方法更新state -> state中的數(shù)據(jù)賦給input的value兵扬。
import React, { PureComponent } from 'react'
export default class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
username: "",
}
}
render() {
return (
<div>
<form onSubmit={e => this.handleSubmit(e)}>
{/* label & htmlFor 聚焦 */}
<label htmlFor="username">
用戶:
<input type="text"
id="username"
onChange={e => this.handleChange(e)}
value={this.state.username}
/>
</label>
<input type="submit" value="提交" />
</form>
</div>
)
}
handleSubmit(event) {
event.preventDefault();
}
handleChange(event) {
console.log(event.target.value);
this.setState({
username: event.target.value,
})
}
}
-
如上綜合稱為受控組件麻裳,這時候只需要提交state中的數(shù)據(jù)即可。
image.png
2.2.1 textarea標(biāo)簽
2.2.2 select標(biāo)簽
import React, { PureComponent } from 'react'
export default class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
fruits: "orange",
}
}
render() {
return (
<div>
<form onSubmit={e => this.handleSubmit(e)}>
<select
name="fruits"
onChange={e => this.handleChange(e)}
value={this.state.fruits}>
<option value="apple">蘋果</option>
<option value="banana">香蕉</option>
<option value="orange">橘子</option>
</select>
<input type="submit" value="提交" />
</form>
</div>
)
}
handleSubmit(event) {
event.preventDefault();
console.log(this.state.fruits);
}
handleChange(event) {
console.log(event.target.value);
this.setState({
fruits: event.target.value,
})
}
}
2.2.3 處理多個輸入
import React, { PureComponent } from 'react'
export default class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
username: "",
password: "",
valid: "",
}
}
render() {
return (
<div>
<form onSubmit={e => this.handleSubmit(e)}>
{/* label & htmlFor 聚焦 */}
<label htmlFor="username">
用戶:
<input type="text"
id="username"
name="username"
onChange={e => this.handleChange(e)}
value={this.state.username}
/>
</label>
<br />
<label htmlFor="password">
密碼:
<input type="text"
id="password"
name="password"
onChange={e => this.handleChange(e)}
value={this.state.password}
/>
</label>
<br />
<label htmlFor="valid">
驗證:
<input type="text"
id="valid"
name="valid"
onChange={e => this.handleChange(e)}
value={this.state.valid}
/>
</label>
<input type="submit" value="提交" />
</form>
</div>
)
}
handleSubmit(event) {
event.preventDefault();
const {username,password,valid} = this.state;
console.log(username,password,valid);
}
handleChange(event) {
// 計算屬性名
this.setState({
[event.target.name]: event.target.value,
})
}
}
三. 非受控組件 (不推薦)
- 推薦:大多數(shù)情況使用受控組件器钟。
- 一個受控組件中津坑,表單數(shù)據(jù)是有React組件來管理的;
- 另一種方式是非受控組件傲霸,這時表單數(shù)據(jù)將交由DOM節(jié)點來處理疆瑰;
- 非受控組件中,通過ref來從DOM節(jié)點中獲取表單數(shù)據(jù)昙啄。
import React, { PureComponent,createRef } from 'react'
export default class App extends PureComponent {
constructor(props) {
super(props);
this.usernameRef = createRef();
}
render() {
return (
<div>
<form onSubmit={e => this.handleSubmit(e)}>
<label htmlFor="username">
用戶:
<input type="text" id="username" ref={this.usernameRef}/>
</label>
<input type="submit" value="提交" />
</form>
</div>
)
}
handleSubmit(event) {
event.preventDefault();
console.log(this.usernameRef.current.value);
}
}