RN电商项目实战——2.组件的State
任何一个复杂的应用,都是由一个简单的应用发展而来的,当应用功能少的时候可能一个组件足够,但是随着功能的增加,把越来越多的功能放到一个组件中就不方便维护管理了。
组件中的数据
React Native 组件的数据分为两种,prop(属性 property的缩写) 和 state(状态) ,无论是属性还是状态的改变,都可能引发组件的重新渲染。
所以,一定要记住一个原则,只能由属性或者状态控制界面显示内容的变化,其它的变量绝对不允许控制显示内容的变化。
归结为一个公式,就像下面这样:
UI=render(data)
公式的含义就是用户看到的界面(UI),应该是render()函数执行的结果,只接受数据(data)作为参数。这是一个毫无副作用的函数,data其实就是 prop 和 state ,两次函数如果输入的属性和状态相同,得到的 UI 一定是一样的。
prop 一般用于组件的对外接口,state 是组件的内部状态。
为了演示 prop 和 state 的使用,我们创建一个选择商品数量的组件。如下图所示:
我们在工程目录下创建 src 目录,这个目录和 android 、ios 目录平级,用来存放 RN 源码,里面创建一个 component 文件夹用来存放自定义组件。
接下来自定义我们第一个组件 Counter ,工程文件路径:/src/component/Counter.js
组件中的 state
组件内部进行渲染主要由 state 控制,RN 中记录组件自身数据变化,必须用 state。
设计 Counter 组件显示内容如上“+” 和 “-” 按钮改变这个计数,这个变化的数据就要通过 state 控制。
初始化 state
通常在组件类的构造函数结尾处初始化 state,在 Counter 构造函数中,通过对 this.state 的赋值完成了对组件 state 的初始化,参考下面代码:
export default class Counter extends Component {
// 构造
constructor(props) {
super(props);
// 初始状态
this.state = {
value: 1
};
}
// ...
}
搭建组件布局文件
组件分为左右各一个按钮,中间是一个输入框。实现代码参照下面代码片段:
参考上面代码片段,TouchableOpacity 控件按下时有高亮显示,是通用的处理按下效果的组件。
activeOpacity
属性是指的按下时的透明度,1 代表完全不透明
onPress
属性是按钮按下的事件
具体参考文档:
http://facebook.github.io/react-native/docs/touchableopacity.html
除了 TouchableOpacity 之外还有 TouchableNativeFeedback 类似组件比较常用,该遵循 Android 质感设计,体验比较好,只不过这个组件只适用于 Android 21版本以上。
有时候我们需要在 Android 21版本上使用 TouchableNativeFeedback,在 iOS 和 Android 低版本上使用 TouchableOpacity。你如果嫌麻烦,可以使用第三方组件 react-native-platform-touchable 地址:
https://github.com/react-community/react-native-platform-touchable
TouchableNativeFeedback
TouchableNativeFeedback 只能包裹一个子组件,所以我们有时候为了替换方便,写 TouchableOpacity 时也只包裹一个子组件,所以写完了TouchableOpacity 然后在里面再定义一个相对多余的 View 当容器并不是什么坏习惯。比如前面的代码可以改成:
<TouchableOpacity activeOpacity={0.2}
onPress={this._reduce.bind(this)}>
<View style={styles.reduce}>
<Text allowFontScaling={false} style={[styles.btn1]}>-</Text>
</View>
</TouchableOpacity>
文本控件 Text allowFontScaling={false} 表示不允许控件跟随手机字体大小变化。
TextInput 是输入框组件,
underlineColorAndroid=”transparent”
是去掉 Android 系统中输入框的下划线。
我们再来看下样式代码,对照着上面代码,里面的组件样式在下面都定义了:
// 样式文件
const styles = StyleSheet.create({
operatingBox: {
width: 120,
height: 35,
borderColor: '#ddd', // 边框颜色
borderWidth: 1,
flexDirection: 'row',//横向布局
alignItems: 'center',
borderRadius: 5, //圆角半径
overflow: 'hidden' // 超出控件范围的隐藏
},
btn1: {
fontSize: 18,
textAlign: 'center',
backgroundColor: 'transparent'
},
inpBox: {
flex: 1,
borderRightWidth: 1,
borderRightColor: '#ddd',
},
reduce: {
width: 34,
height: 34,
justifyContent: 'center',
borderRightWidth: 1,
borderRightColor: '#ddd',
},
plus: {
width: 34,
height: 34,
justifyContent: 'center'
},
inp1: {
flex: 1,
backgroundColor: 'transparent',
textAlign: 'center',
padding: 0,
fontSize: 14
},
});
读取和更新 state 变量
TextInput 组件中的 value 属性定义了输入框的内容,在这里用状态机变量控制显示, this.state.value.toString() 。
TouchableOpacity 组件通过 onPress 绑定了按钮的回调方法,onPress={this._reduce.bind(this)} 这里记得对方法进行绑定操作,否则在方法里无法使用 this 变量。
_reduce() 和 _plus() 方法分别通过 this.setState 函数修改了状态机变量的值。
在代码中,通过 this.state 可以读取到组件的当前 state 。值得注意的是,我们改变组件 state 必须要使用 this.setState 函数,而不能直接去修改 this.state。 当调用this.setState 函数才会驱动组件去更新,界面才会重新渲染。于是当我们点击 “+” 或者 “-” 的时候就可以看到界面的变化。
完善输入框
输入框也可以监听输入内容修改状态机变量,修改上面的代码:
<TextInput style={styles.inp1}
returnKeyType='done'
maxLength={3}
onEndEditing={this._checkNumber.bind(this)}
value={this.state.value.toString()}
keyboardType="numeric"
onChangeText={(txt) => this.setState({value:Number(txt)})}
autoFocus={false}
underlineColorAndroid="transparent">
</TextInput>
keyboardType 约束了软键盘类型,numeric 是数字类型键盘
returnKeyType 添加了完成的返回按钮
onChangeText 文本输入框变化的时候回调改方法,在这里修改了状态机变量
-
onEndEditing 输入完成的时候回调方法,调用了下面的 _checkNumber 方法。里面对输入内容做了处理,不允许 value 小于 1,并修改了状态机变量。
_checkNumber(){
let value=this.state.value;
if(value===''||value<1){
value=1;
}else{
value=Math.floor(value); //舍去小数
}
this.setState({value:value})
}
虽然每次 setState 每次都刷新界面,大家不用考虑性能的问题,RN 框架都已经处理了。 查看性能方式:
Android模拟器 Ctrl/Command + M
iOS 模拟器 Command + D
调出调试菜单,点击 Show Perf Monitor, 如下图所示,当我们点击的时候并没有明显的影响性能,release版本比测试阶段性能消耗会进一步降低。
查看代码
参考React Native电商项目实战——开篇 示例代码可在 GitHub 上获取
https://github.com/yll2wcf/TShop
如果你已经从 GitHub 上克隆了这个程序的 Git 仓库,那么可以执行 git checkout 2a 签出程序的这个版本。 需要执行 npm install 或 yarn install
关注本公众号或者关注卓朗科技技术中心,回复RN 即可查看视频地址。