前言
ReactNative内部分别使用了props, state来区分组件的属性和状态。props用来定义组件外部传进来的属性, 属于那种经过外部定义之后, 组件内部就无法改变。而state维持组件内部的状态更新和变化, 组件渲染出来后响应用户的一些操作,更新组件的一些状态。如果组件内部状态不需要更新,即没有调用过
this.setState
, 全部通过props来渲染也是没问题的, 不过这种情况不常见。本文所介绍的内容就是通过props和state的定义来谈谈ReactNative的受控组件和非受控组件。
通过
this.setState来控制组件的更新和变化,和iOS原生开发中控制组件变化的思想是有很大区别的,iOS中可以直接设置控件的属性值。初次接触
ReactNative中的这种设计思想还是挺难的。非受控组件
顾名思义, 非受控组件即组件的状态改变不受控制.接来下我们以一个简单TextInput组件代码来描述。
在这个最简单的输入框组件里,我们并没有干涉TextInput中的value展示,即用户通过键盘输入的内容都会展示在上面,但是不能从其他地方改变其内容。
<TextInput
/>
在这个最简单的输入框组件里,我们并没有干涉TextInput中的value展示,即用户通过键盘输入的内容都会展示在上面,但是不能从其他地方改变其内容。
受控组件
上面提到过,既然通过设置input的value属性, 无法改变输入框值,那么我们把它和state结合在一起,再绑定onChange事件,实时更新value值就行了
constructor(props) {
super(props);
this.state = {
value: "",
}
}
handleChange(e) {
this.setState({
value: e.nativeEvent.text
})
}
render() {
return (
<TextInput
style={styles.style_user_input}
value={this.state.value}
onChange={e => this.handleChange(e)}
/>
);
}
这就是最简单的受控组件模型, 我们可以通过在onChange的回调里控制input要显示的值,
给value赋予this.state.value,通过setState对state的value进行更新,这时会出发render刷新页面,就会执行到value={this.state.value},TextInput中的内容就得到了更新。
举两个简单的应用场景例子:
1.点击一个按钮,TextInput中的内容增加一个特定字符串,比如聊天界面点击emoji表情,输入框增加一段“[微笑]”;
2.点击另一个按钮,获取到TextInput中的内容,比如说聊天界面的发送消息。
第一个场景目的是要从外部给TextInput输入内容,第二个场景是要从外部取到TextInput的内容。这两个操作都离不开state。
示例
下面展示一个简单的demo:
完整代码:
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
Image,
View,
TextInput,
TouchableOpacity,
} from 'react-native';
class RNTextIput extends Component {
constructor(props) {
super(props);
this.state = {
value: "",
gotText: "",
}
}
handleChange(e) {
this.setState({
value: e.nativeEvent.text
})
}
sendAction() {
this.setState({
gotText: this.state.value
})
}
render() {
return (
<View style={{backgroundColor:'#f4f4f4',flex:1}}>
<TextInput
style={styles.style_user_input}
placeholder='QQ号/手机号/邮箱'
numberOfLines={1}
autoFocus={true}
underlineColorAndroid={'transparent'}
textAlign='center'
value={this.state.value}
onChange={e => this.handleChange(e)}
/>
<TextInput
style={styles.style_pwd_input}
numberOfLines={1}
autoFocus={true}
underlineColorAndroid={'transparent'}
textAlign='center'
value={this.state.gotText}
/>
<View style={{height:1,backgroundColor:'#f4f4f4'}} />
<TouchableOpacity
onPress={() => {
this.sendAction();
}}
>
<View style={styles.style_view_commit} >
<Text style={{color:'#fff'}}>
发送
</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
this.setState({value:this.state.value + "文字~"});
}}
>
<View style={styles.style_view_commit} >
<Text style={{color:'#fff'}}>
手动加入文字
</Text>
</View>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
style_image:{
borderRadius:35,
height:70,
width:70,
marginTop:40,
alignSelf:'center',
},
style_user_input:{
backgroundColor:'#fff',
marginTop:100,
height:35,
},
style_pwd_input:{
backgroundColor:'#fff',
height:35,
marginTop:10,
},
style_view_commit:{
marginTop:15,
marginLeft:10,
marginRight:10,
backgroundColor:'#63B8FF',
height:35,
borderRadius:5,
justifyContent: 'center',
alignItems: 'center',
},
});
AppRegistry.registerComponent('RNTextIput', () => RNTextIput);
参考: