首页 技术 正文
技术 2022年11月18日
0 收藏 976 点赞 2,249 浏览 2613 个字

背景

React内部分别使用了props, state来区分组件的属性和状态。props用来定义组件外部传进来的属性, 属于那种经过外部定义之后, 组件内部就无法改变。而state维持组件内部的状态更新和变化, 组件渲染出来后响应用户的一些操作,更新组件的一些状态。如果组件内部状态不需要更新,即没有调用过this.setState, 全部通过props来渲染也是没问题的, 不过这种情况不常见。本文所介绍的内容就是通过props和state的定义来谈谈React的受控组件和非受控组件。

非受控组件

顾名思义, 非受控组件即组件的状态改变不受控制.接来下我们以一个简单input组件代码来描述。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';class Demo1 extends Component {
render() {
return (
<input />
)
}
}ReactDOM.render(<Demo1/>, document.getElementById('content'))

在这个最简单的输入框组件里,我们并没有干涉input中的value展示,即用户输入的内容都会展示在上面。如果我们通过props给组件设置一个初始默认值,<input defaultValue={this.props.value}/>defaultValue属性是React内部实现的一个属性,目的类似于input的placeholder属性。

ps: 此处如果使用value代替defaultValue,会发现输入框的值无法改变。

受控组件

上面提到过,既然通过设置input的value属性, 无法改变输入框值,那么我们把它和state结合在一起,再绑定onChange事件,实时更新value值就行了。

class Demo1 extends Component {
constructor(props) {
super(props);
this.state = {
value: props.value
}
} handleChange(e) {
this.setState({
value: e.target.value
})
} render() {
return (
<input value={this.state.value} onChange={e => this.handleChange(e)}/>
)
}
}

这就是最简单的受控组件模型, 我们可以通过在onChange的回调里控制input要显示的值,例如我们设置input框只能输入数字

this.setState({
value: e.target.value.replace(/\D/g, '')
})

现在我们应该完全明白form表单中受控组件和非受控组件的关系。受控组件采取的理念类似于redux的单项数据流理念,即value值是在调用者上更新的。

那么问题来了。。。

最后的思考

现在我们要实现一个简单的input的number类型组件,后面紧跟一个+的button按钮,将输入框内的数字每次加一。所以此处只能按照受控组件的理念来写

import React, { Component } from 'react';export default class extends Component {
constructor(props) {
super(props);
this.state = {
value: props.value
}
} handleChange(e) {
this.setState({
value: e.target.value.replace(/\D/g, '')
})
} plus() {
const value = ++this.input.value
this.setState({
value,
})
} render() {
return (
<div>
<input
value={this.state.value}
onChange={e => this.handleChange(e)}
ref={ref => this.input = ref}
/>
<button onClick={() => this.plus()}>+</button>
</div>
)
}
}

此处功能基本实现完全,但是发现使用此组件之后,面临了另一个问题,我们如何在外部获取到这个输入框的值。一种方法是给组件增加个getValue回调的props,每次value值变化都调用一次getValue,即在handleChange和plus函数里调用,但是存在一个问题是,调用者只能通过getValue被动获取值,而且value值得改变此时还是在组件内部自行变化,不符合受控组件原理,也不满足React单向数据流概念。另一种方法就是将input组件的将要改变的值传到调用者里面,由调用者来决定更不更新组件的值,即此时数据由被调用者input组件生成,传至调用者,调用者判断满足条件后决定更新,再将数据重新传入到被调用者里。而调用者与被调用者彼此之间建立的联系方式通过input组件的props和调用者的state。此时input组件的代码如下

export default class extends Component {
constructor(props) {
super(props);
this.state = {
value: props.value
}
} componentWillReceiveProps(nextProps) {
this.setState({
value: nextProps.value
})
} handleChange(e) {
this.props.onChange(e.target.value)
} plus() {
const value = ++this.input.value
this.props.onChange(value)
} render() {
return (
<div>
<input
value={this.state.value}
onChange={e => this.handleChange(e)}
ref={ref => this.input = ref}
/>
<button onClick={() => this.plus()}>+</button>
</div>
)
}
}

代码中的this.props.onChange就是调用者内部的函数,通过setState来更新input组件的value值。完整代码已放到github,欢迎指正交流。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,983
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,500
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,344
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,127
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,761
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,838