共计 4373 个字符,预计需要花费 11 分钟才能阅读完成。
快来退出咱们吧!
“ 小和山的菜鸟们 ”,为前端开发者提供技术相干资讯以及系列根底文章。为更好的用户体验,请您移至咱们官网小和山的菜鸟们 (https://xhs-rookies.com/) 进行学习,及时获取最新文章。
“Code tailor”,如果您对咱们文章感兴趣、或是想提一些倡议,微信关注 “小和山的菜鸟们” 公众号,与咱们取的分割,您也能够在微信上观看咱们的文章。每一个倡议或是同意都是对咱们极大的激励!
前言
这节咱们将介绍 React
中受控组件和非受控组件的概念及其应用。
本文会向你介绍以下内容:
- 什么是受控组件 / 非受控组件
- 受控组件
- 非受控组件
什么是受控组件 / 非受控组件
在 HTML
中,表单元素如 <input>
,<textarea>
和 <select>
表单元素通常放弃本人的状态,并依据用户输出进行更新。而在 React
中,可变状态个别保留在组件的 state(状态)
属性中,并且只能通过 setState()
更新。
咱们能够通过使 React
的 state
成为“繁多数据源准则”来联合这两个模式。而后渲染表单的 React 组件也能够管制在用户输出之后的行为。
这种模式,其值由 React
管制的输出表单元素称为“受控组件”。
那么相同的,值并不禁 React
进行管制,该组件本人输出,缩小等等,该元素成为非受控组件。
对于什么时候应用受控组件,什么时候应用非受控组件,能够查看这一篇文章:
Controlled and uncontrolled form inputs in React don’t have to be complicated – Gosha Arinich (goshakkk.name)
受控组件
意识受控组件
默认提交表单形式
HTML
表单元素与 React
中的其余 DOM
元素有所不同,因为表单元素天然地保留了一些外部状态。
例如,这个纯 HTML
表单承受一个独自的 name
:
<form>
<label>
名字:
<input type="text" name="name" />
</label>
<input type="submit" value="提交" />
</form>
该表单和 HTML
表单的默认行为统一,当用户提交此表单时浏览器会关上一个新页面。如果你心愿 React
中放弃这个行为,也能够工作。
然而少数状况下,咱们会让 React
组件来治理这些数据,并在点击提交这些数据并触发关上新页面的操作。
这就用到了“受控组件(controlled components
)”。
受控组件提交表单
在 HTML
中,表单元素(如<input>
、<textarea>
和 <select>
)之类的表单元素通常本人保护 state,并依据用户输出进行更新。
而在 React
中,可变状态(mutable state
)通常保留在组件的 state 属性中,并且只能通过应用 setState()
来更新。
- 咱们将两者联合起来,使
React
的state
成为“惟一数据源”; - 渲染表单的
React
组件还管制着用户输出过程中表单产生的操作; - 被
React
以这种形式管制取值的表单输出元素就叫做“受控组件”;
例如,如果咱们想让前一个示例在提交时打印出名称,咱们能够将表单写为受控组件:
class App extends PureComponent {constructor(props) {super(props)
this.state = {username: '',}
}
render() {const { username} = this.state
return (
<div>
<form onSubmit={(e) => this.handleSubmit(e)}>
<label htmlFor="username">
用户名:
<input
type="text"
id="username"
onChange={(e) => this.handleUsernameChange(e)}
value={username}
/>
</label>
<input type="submit" value="提交" />
</form>
</div>
)
}
handleUsernameChange(event) {
this.setState({username: event.target.value,})
}
handleSubmit(event) {console.log(this.state.username)
event.preventDefault()}
}
因为在表单元素上设置了 value
属性,因而显示的值将始终为 this.state.value
,这使得 React 的 state 成为惟一数据源。
因为 handleUsernameChange
在每次按键时都会执行并更新 React
的 state
,因而显示的值将随着用户输出而更新。
非受控组件
Ref 的创立和应用
在 React
的开发模式中,通常状况下不须要、也不倡议间接操作 DOM
原生,然而某些非凡的状况,的确须要获取到 DOM
进行某些操作:
- 治理焦点,文本抉择或媒体播放。
- 触发强制动画。
- 集成第三方
DOM
库。
咱们这里如果应用非受控组件就会有一个问题,如何获取该组件的数据,这里就能够用 Refs
来获取该组件,而后就能够获取到该组件的数据了。因而咱们先简述 Refs
的内容。
留神:当然还有其余的办法能够获取组件内容,例如:变量晋升到父组件对立治理、事件监听。
创立 ref 的形式
如何创立 refs
来获取对应的 DOM
呢?目前有三种形式:
- 形式一:传入字符串
应用时通过 this.refs. 传入的字符串
格局获取对应的元素;
- 形式二:传入一个对象
对象是通过 React.createRef()
形式创立进去的;应用时获取到创立的对象其中有一个 current
属性就是对应的元素;
- 形式三:传入一个函数
该函数会在 DOM
被挂载时进行回调,这个函数会传入一个 元素对象,咱们能够本人保留;应用时,间接拿到之前保留的元素对象即可;
代码演练:
class App extends PureComponent {constructor(props) {super(props)
this.titleRef = createRef()
this.titleEl = null
}
render() {
return (
<div>
<h2 ref="title">String Ref</h2>
<h2 ref={this.titleRef}>Hello Create Ref</h2>
<h2 ref={(element) => (this.titleEl = element)}>Callback Ref</h2>
<button onClick={(e) => this.changeText()}> 扭转文本 </button>
</div>
)
}
changeText() {
this.refs.title.innerHTML = '你好啊, 小和山的菜鸟们'
this.titleRef.current.innerHTML = '你好啊, 小和山的菜鸟们'
this.titleEl.innerHTML = '你好啊, 小和山的菜鸟们'
}
}
Ref 节点的类型
ref
的值依据节点的类型而有所不同:
- 当
ref
属性用于HTML
元素时,构造函数中应用React.createRef()
创立的ref
接管底层DOM
元素作为其current
属性; - 当
ref
属性用于自定义class
组件时,ref
对象接管组件的挂载实例作为其current
属性; - 你不能在函数组件上应用
ref
属性,因为他们没有实例;
这里咱们演示一下 ref
援用一个 class
组件对象:
class Counter extends PureComponent {constructor(props) {super(props)
this.state = {counter: 0,}
}
render() {
return (
<div>
<h2> 以后计数: {this.state.counter}</h2>
<button onClick={(e) => this.increment()}>+1</button>
</div>
)
}
increment() {
this.setState({counter: this.state.counter + 1,})
}
}
class App extends PureComponent {constructor(props) {super(props)
this.counterRef = createRef()}
render() {
return (
<div>
<Counter ref={this.counterRef} />
<button onClick={(e) => this.increment()}>app +1</button>
</div>
)
}
increment() {this.counterRef.current.increment()
}
}
函数式组件是没有实例的,所以无奈通过 ref
获取他们的实例,然而某些时候,咱们可能想要获取函数式组件中的某个 DOM
元素,这个时候咱们能够通过 React.forwardRef
,前面咱们也会学习 hooks
中如何应用 ref
。
意识非受控组件
React
举荐大多数状况下应用受控组件来解决表单数据:
- 一个受控组件中,表单数据是由
React
组件来治理的; - 另一种代替计划是应用非受控组件,这时表单数据将交由
DOM
节点来解决;
如果要应用非受控组件中的数据,那么咱们须要应用 Ref
来从 DOM
节点中获取表单数据。
咱们来进行一个简略的演练:
- 应用
ref
来获取input
元素; - 在非受控组件中通常应用
defaultValue
来设置默认值;
class App extends PureComponent {constructor(props) {super(props)
this.usernameRef = createRef()}
render() {
return (
<div>
<form onSubmit={(e) => this.handleSubmit(e)}>
<label htmlFor="">
用户:
<input defaultValue="username" type="text" name="username" ref={this.usernameRef} />
</label>
<input type="submit" value="提交" />
</form>
</div>
)
}
handleSubmit(event) {event.preventDefault()
console.log(this.usernameRef.current.value)
}
}
同样,<input type="checkbox">
和 <input type="radio">
反对 defaultChecked
,<select>
和 <textarea>
反对 defaultValue
。
下节预报
本节咱们学习了 React
中控组件和非受控组件的内容,在下一个章节咱们将持续学习 React
中高阶组件以及组件补充的内容,敬请期待!