一. refs的使用##
React开发模式中,通常情况不需要,也不建议直接操作DOM元素,但是某些特殊的情况,确实需要获取到DOM进行某些操作。
- 管理焦点,文本选择/媒体播放;
- 触发强制动画;
- 集成第三方DOM库。
如何创建refs来获取对应的DOM?三种方式。
1.1 创建方式
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="字符串/对象/回调函数">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. 使用方式一:字符串(不推荐,后续可能删除)
this.refs.titleRef.innerHTML = "Hello wwq"
// 2. 使用对象(推荐)
this.titleRef.current.innerHTML = "Hello wwq"
// 3. 使用回调函数
console.log(this.titleEl);
this.titleEl.innerHTML = "Hello jsx3"
}
}
- 传入字符串
- 传入一个对象,官方推荐,取的时候要导入createRef库,用其实例的current属性。 - 传入回调函数
1.2 ref节点类型
ref用于html元素时,构造函数中使用React.createRef()创建的ref接收底层DOM元素作为其current属性。
ref用于自定义class组件时,ref对象接收组件的挂载实例作为其current属性。
不能在函数组件上使用ref属性,因为他们没有实例。
但有时,我们想要获取函数组件中的某个DOM元素。
这个时候我们可以通过React.forwardRef,之后学习hooks中使用refs。
二. 受控组件##
2.1 认识受控组件
- 在React中,HTML表单的处理方式和普通的DOM元素不太一样;表单元素通常会保存在一些内部的state。
- HTML中,(input, textarea, select)之类的表单元素通常自己维护state,并根据用户输入进行更新。
- 而在React中,可变状态mutable state通常保存在组件的state属性中,并且只能通过使用setState()来更新。
- 我们将两者结合起来,使React的state成为“唯一数据源”;
- 渲染表单的React组件还控制着用户输入过程中表单发生的操作;
- 被React以这种方式控制取值的表单输入元素就叫做“受控组件”。
2.1.1 默认提交表单方式
2.2 常见表单的处理
- 通过给form绑定onSubmit事件来更改默认行为。
- 给input绑定onChange事件来监听输入变化。
- 为了输入框和state中数据保持一致,我们需要同步到value,单向数据流:input中输入,触发onChange -> onChange调用handleChange方法更新state -> state中的数据赋给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中的数据即可。
2.2.1 textarea标签
2.2.2 select标签
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,
})
}
}
三. 非受控组件 (不推荐)
- 推荐:大多数情况使用受控组件。
- 一个受控组件中,表单数据是有React组件来管理的;
- 另一种方式是非受控组件,这时表单数据将交由DOM节点来处理;
- 非受控组件中,通过ref来从DOM节点中获取表单数据。
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);
}
}